インデックス

SQLServer【Index編】#S2_13_クラスター化インデックスの検索

前回はクラスター化インデックスの内部構造を解説しました。

クラスター化インデックスを作成したことによる変化

現状はCreateDate指定で検索するとクラスター化インデックスシークになるという状態になりましたが,以前実施していたId指定でのSQLをもう一度実行してみましょう。

実行プランの確認

実行プランを確認すると,以前と変化している場所があります。IndexSeekになっている場所は以前と同じです。ちがうのは,「キー参照」となっている場所です。これは以前RIDLookupになっていましたね。でも現在は「キー参照」になっています。これはクラスター化インデックスを作成したことによる変化です。

キー参照とは

先述した通り,クラスター化インデックスを作成したことによって,実データという考え方が無くなり,クラスター化インデックスの終端であるリーフページに実データが移りました。なので,実データの時に使っていた実データのファイルの場所と行番号であるRIDという考え方もなくなりました。では代わりにどうなったかというと,非クラスター化インデックスのリープページには,RIDの代わりに,クラスター化インデックスを検索するためのKeyが入っています。今回の例でいえばCreateDateが入っているという事になります。なので,Idの非クラスター化インデックスの終端には,IdとCreateDateが入っています。

非クラスター化インデックスの内部構造(クラスター化インデックスありの場合)

図のように,非クラスター化インデックスのリープページには,クラスター化インデックスのKeyが入っています。今までは,RIDを参照して実データを検索していたので,RIDLookupになっていましたが,クラスター化インデックスを作成後は,クラスター化インデックスのKeyでクラスター化インデックスを検索しに行くので,実行プランでは「キー参照」という表現になっています。

クラスター化インデックスと非クラスター化インデックスの速度の違い

先述の通り,クラスター化インデックスはリープページに実データがあるので,検索は1回で済みますが,非クラスター化インデックスの場合はリープページにクラスター化インデックスのKeyがあるだけなので,そのKeyでもう一度クラスター化インデックスの検索が必要です。なので非クラスター化インデックスは2段階で検索することになります。という事は当然非クラスター化インデックスの方が,検索には時間がかかります。

現状このSQLのように検索結果が1行になるような場合は,速度的に違いは感じませんが,検索結果が多い場合は,それだけ非クラスター化インデックスはキー参照が発生するので,その分検索には時間がかかるという事になります。

大量データがヒットするように検索

次のSQLを実行すると10400件がヒットします。

これで一度実行してください。

私の環境では検索に「3秒」程度かかりました。

実行プランを確認すると,クラスター化インデックスシークになっているため,インデックスはうまく機能していますが,推定コストを確認すると,1行ヒットする時とくらべてか習い値が大きくなっていることが分かります。1万件のデータを取得するには,それなりに開く必要があるファイルが大量にあったという事です。

続いて,非クラスター化インデックスで確認してみましょう。

このようにId指定で10400件ヒットするSQLを実行します。

私の環境では7秒かかりました。やはり,非クラスター化インデックスの方が,時間がかかるという事が確認できます。

実行プランを見ると,IndexSeekでキー参照にはなっていますが,推定コストが高いことが分かります。

このようにクラスター化インデックと非クラスター化インデックスの検索の違いはあるので,どうしても速度が出ない非クラスター化インデックスの場合は,テーブル設計を見直す必要があります。例えば今回の社員テーブルの例で言うと,Bikou列が7900バイトでわざと大きな列にしていますが,そのせいで,物理的なファイル量が多くなっています。この辺りを別の表にすることで,キー参照で読み込むファイル数が減るので,検索が速くなるという事は見込めます。

SQLServerインデックスを理解して検索を高速にする方法