「インデックスを付けたのに遅い」「実行計画を見ても何を確認すればいいか分からない」は SQL Server あるある。
この記事では、実行計画の見方とインデックスが使われないときの切り分けをざっくり逆引きする。
先に結論
- 遅いクエリはまず実際の実行計画を見る
- インデックスが使われない理由は「条件とキーの不一致」「統計情報」「選択性」が多い
- Index Seek だけ見て安心しない(Lookup や Sort のコストも見る)
実行計画の取り方
- SSMS で「実際の実行計画を含める」
- 論理読み取りも見たいなら統計情報表示を併用
- 重いクエリは推定より実際を優先
例: Orders を CustomerId と OrderDate で絞り込むクエリを対象に、実際の計画を取得して高コスト箇所を確認する。
まず見るポイント
- 高コストな演算子はどれか(Scan / Seek / Join / Sort / Lookup)
- 見積もり行数と実際行数のズレ
- Seek なのに Lookup が多くないか
- Join の選び方が妥当か
インデックスが使われない主な原因
1. 先頭列と検索条件が合っていない
複合インデックス (CustomerId, OrderDate) に対して OrderDate だけで絞ると使われにくい。
2. 列を加工して比較している
年だけ取り出すような加工比較は効きにくい。日付は範囲条件(以上・未満)に書き換える。
3. 型が食い違っている
パラメータ型と列型が違うと変換が入り、Seek しづらくなることがある。
4. 選択性が低い
値が偏っている列だと、最適化が Scan を選ぶことがある。
5. 統計が古い
行数見積もりがズレると、計画が不安定になりやすい。
切り分け手順
- 遅いクエリを特定する
- 実際の実行計画で高コスト箇所を洗う
- 使われない理由を上記パターンに当てる
- 必要ならカバー列追加や条件の書き換えを試す
- 変更前後で論理読み取りと時間を比較する
ざっくりまとめ
- 実行計画は「どこが重いか」を見る道具
- インデックス不足だけでなく、条件・統計・型も疑う
- Seek でも Lookup / Sort が多いなら改善余地あり