SQL チューニングは『計測→仮説→検証』のループ
RDBMS のパフォーマンス問題の多くはチューニングで大きく改善できます。本記事では編集部の視点で、実行計画とインデックスを中心に公開情報をもとに整理します。PostgreSQL 実践 もご参考に。
遅いクエリの見つけ方
(1) スロークエリログ:閾値超のクエリを記録。(2) pg_stat_statements:頻度+合計時間。(3) APM:Datadog/New Relic でクエリレベル可視化。(4) p95/p99 で問題発見:平均だけ見ない。(5) ビジネスインパクトで優先順位:呼び出し回数×時間。Observability 実践 も合わせて。
実行計画の読み方
(1) EXPLAIN ANALYZE:実測コスト+行数。(2) Seq Scan:全表スキャン。大表で危険。(3) Index Scan / Bitmap Scan:インデックス利用。(4) Nested Loop / Hash Join / Merge Join:結合戦略。(5) actual vs estimated:見積り誤差で統計更新を検討。
インデックス戦略
(1) WHERE/JOIN/ORDER BY の列に貼る。(2) 複合インデックス:左から使う。(3) カバリング:INCLUDE 句で SELECT 列を含める。(4) 部分インデックス:WHERE 条件付き。(5) 過剰なインデックスは害:INSERT/UPDATE が遅くなる。
クエリ書換のテクニック
(1) N+1 を JOIN で1クエリ化。(2) EXISTS vs IN:大きいデータでは EXISTS が速いことが多い。(3) UNION ALL vs UNION:重複削除不要なら ALL。(4) LIMIT で早期終了:取得行数を絞る。(5) 共通テーブル式 (CTE):読みやすさと最適化のバランス。
大規模データの工夫
(1) パーティショニング:日付/IDで分割。(2) マテリアライズドビュー:集計を事前計算。(3) 並列クエリ:max_parallel_workers 設定。(4) VACUUM/ANALYZE:統計情報を最新に。(5) キャッシュ層:Redis で頻出クエリをキャッシュ。Redis 実践 も合わせて。
失敗しがちなパターン
(1) SELECT *:転送量が無駄。(2) LIKE %xxx%:インデックス効かない。(3) NULL の扱い:IS NULL は別途検討。(4) 関数を WHERE で適用:インデックス無効化。(5) 巨大IN リスト:1000件超で遅延。対策は、(1)必要列のみ、(2)前方一致/全文検索、(3)NOT NULL DEFAULT、(4)関数インデックス、(5)バッチ分割、です。