kagamihogeの日記

kagamihogeの日記です。

インデックスがあるのにフルスキャン?

「なんか遅いから早くして(意訳)」という仕事が回ってきた。大量データ投入後の試験待たずとも、遅いのは前々から分かってたから覚悟は出来てたんだけど・・・人外魔境と化したコードにどう手を入れたもんですかねぇ。

さて。何はともあれ計測一番。SQL Server Profiler を起動して、ブラウザから遅いといわれる機能のボタンを押してみる。・・・とスクロールバーがあっという間に小さくなってしまった。すごい参照系だなぁと思いつつ発効されたクエリ数を見るとその数 400。400 個の SELECT で出来てる画面って・・・一体・・・。

ログを見ると似たようなクエリを大量に出してるので、そういう個所を一つずつ作り直すしかないかなぁ・・・と思っているとログの中に 1 分近くかかっているクエリを発見。このクエリもまた数回走っており、一回ボタン押したら 5 分くらい返って来ない主原因になっている様子。

で、そのクエリはというと

SELECT * FROM HOGE_TABLE WHERE HOGE_ID = 12345

異様に遅くなるようには見えない単純な代物。データ数は・・・200 万件。それなりに多いけど、インデックスのある列を見るだけだから 1 分はどうもおかしい。

というわけで実行計画を見てみる。と、Clustered Index Scan と出てくる。ん?なんで Index Scan になるんだ?と思ってテーブル定義を見てみると・・・インデックス張ってある列が 2 つある。

なるほど、と思いつつ試しに下のクエリを投げて見ると

SELECT * FROM HOGE_TABLE WHERE HOGE_ID = 12345 AND HOGE_ID_2 = 54321

やはり 1 秒以下で返って来る。実行計画も Clustered Index Seek になっており、違いは明らか。

インデクッス張ってある列が 2 つあり、片方しか WHERE に入れていない。そのため、インデックスに対してフルスキャンがかかっていたと。

よくよく考えてみれば自明なことだけど、なるほどなぁ・・・と納得してしまった。