インデックス

SQLServer【Index編】#S2_09_非クラスター化インデックスの内部構造

前回は非クラスター化インデックスを作って,実行プランでは「IndexSeek」と「RIDLookupになっていることを確認しました。前述した通り,SeekかScanに注目し,Scanなら全部読んでしまっている,Seekならピンポイントでうまく動いていると解釈してください。

Scanには「TableScan」だけでなく「IndexScan」というのも存在し,Indexとついているから,Indexがうまく動作しているように誤解するかもしれませんが,「Scan」なので,インデックスをすべて読んだという意味になります。これも,ポイントでは見つけられず,すべてを読んだということなので,インデックスをうまく使えていない状態です。

非クラスター化インデックスの内部構造

実表データ

非クラスター化インデックスの内部構造としては,まず,実表データ領域というものがあります。これはそのまま実際のデータで,SQLServerでは8キロバイトごとのファイルが複数ある形で存在しています。インデックスがない場合はこの実表データのみが存在していることになります。

非クラスター化インデックスを作成すると

非クラスター化インデックスを作成する,インデックスファイルが作成されます。今回のようにIdでインデックスを作成すると,Idの順序でインデックスファイルが作られます。インデックスファイルは,ツリー構造になっていて,「1~102」までは「インデックスファイルA」にあるよって感じで,次にインデックスAファイルを読むと「1から50はインデックスファイルA2にあるよ」って感じで,たどれるようになっています。そのインデックスファイルをたどっていくと,インデックスの終端があり,これを「リーフページ」と呼んでいます。

リーフページ

リーフページはインデックスの項目とRIDが入っています。今回の例であれば,Idのインデックスなので,「Id」と「RID」が入っていて,1~50までのIdとRIDが入っているという感じです。

RID

RIDとは実表データの行情報です。インデックスのリーフページには「Id」と「RID」しかないので,実表データから,社員データの姓名などを取ってこないといけません。そのために実表データがどのファイルの何行目にあるかという情報が入っています。先述の通り,実表データは8キロバイトの大量のファイルの集まりなので,どのファイルの何行目にデータがあるという情報があれば,ピンポイントでデータを取得することができます。こうやってインデックスファイルをツリー状にたどって,リーフページに行きつくことをIndexSeekといいます。要するに,インデックスをツリー状にたどり,ピンポイントにRIDを取得することで,どのファイルの何行目に欲しいデータがあるという事が分かります。そして,このRIDから必要なデータを取得することをRIDLockupといいます。

RIDLockup

インデックスのリーフページのRIDから実データの所在を割り出し,データを取りに行くことを,RIDLookupといい,社員テーブルをId指定で検索したときに,IndexSeek+RIDLookupになっていたという事は,「Id=1」で非クラスター化インデックスを探索し,ピンポイントでリーフページたどり着いたことをIndexSeekといい,そのIndexSeekしたリーフページにあるRIDで実データの場所を割り出し,実データを取りだしたことをRIDLookupと呼んでいます。なので,今回の非クラスター化インデックスは期待通りに機能したという事になります。

非クラスター化インデックスの内部構造(別表)

非クラスター化インデックスの内部構造を別の図で示します。前述の通り,ルートページからId順でたどり,リーフページにたどり着いた後に,RIDで実データを取得するという構造になります。

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