EXPLAIN の読み方・コスト・チューニング手順を完全習得
オプティマイザが SQL を実行する際に選んだ具体的な手順のツリー。EXPLAIN コマンドで確認でき、性能チューニングの最初の一歩。
EXPLAIN SELECT * FROM 受注 WHERE 顧客ID = 'C01'; -- PostgreSQL の例(概念的な出力) -- Index Scan using idx_顧客ID on 受注 -- Index Cond: (顧客ID = 'C01') -- cost=0.43..4.45 rows=1 width=80
| 操作名 | 意味 | 性能 |
|---|---|---|
| Index Scan / Index Seek | インデックスを使った検索 | ✅ 速い |
| Seq Scan / Full Table Scan | テーブル全行スキャン | ⚠ 大テーブルで遅い |
| Index Only Scan | インデックスだけで完結(カバリング) | ✅✅ 最速 |
| Nested Loop | ネストループ結合 | 内側にインデックスで高速 |
| Hash Join | ハッシュ結合 | 大テーブル同士に有効 |
| Sort | ソート操作 | メモリ超過でディスク使用 |
| Bitmap Heap Scan | ビットマップを作ってからヒープ読み込み | 中規模の IN 条件等 |
| 項目 | 意味 |
|---|---|
| cost=0.43 | 最初の行を返すまでのコスト(スタートアップコスト) |
| cost=..8.45 | 全行を返し終えるまでの総コスト |
| rows=10 | 返される推定行数 |
| width=80 | 1 行あたりの推定バイト数 |
コストは単位(ディスクページ読み込み)を基準とした相対値。絶対値より親ノードと子ノードの大小関係が重要。
| 実行計画の症状 | 原因 | 改善策 |
|---|---|---|
| Full Table Scan / Seq Scan | インデックスなし・統計情報古い | インデックス追加・ANALYZE 実行 |
| Sort(大量行) | ORDER BY / GROUP BY 列にインデックスなし | ソート列にインデックス追加 |
| Hash Batches > 1 | ハッシュ表がメモリに収まらない | work_mem 増加・結合順序変更 |
| rows 推定値と実際値の乖離 | 統計情報が古い | ANALYZE / UPDATE STATISTICS |
-- Oracle のヒント句(最終手段) SELECT /*+ INDEX(c idx_顧客名) */ c.顧客ID, c.顧客名 FROM 顧客 c WHERE c.顧客名 = '山田';
読了ボタンを押すとトップページの進捗に反映されます