任意の要素(列)に索引を作成する
リレーショナル・モデル用語では、表の行を一意に特定することができる列をプライマリ・キーと言います。一般的に、プライマリ・キーが一意であることの実装には索引が使用されています。ある値がすでに列に存在するかどうかは索引を探索すると短時間で判明するので、追加しようとしたデータの値が既存データと重複するかの判定ができます。索引が持つ値に重複がないことをもって列の値が一意であることの保証になっています。
一般的に、クエリーが検索条件に指定する列はプライマリ・キーだけとは限りません。それ以外の列(要素)が検索条件になることもあります。そのために、プライマリ・キー以外の列にも索引を作成することがあります。DBMSの実装によって、プライマリ・キー列とそれ以外の列で索引の実装が異なります。
主な実装としては以下の2パターンがあります。
- すべての索引が値と行アドレスへのポインタの組を持っている
- プライマリ・キー索引の値を指す2次索引
すべての索引が行アドレスを指すヒープ表[*2]の場合、表に作成する索引はどの列でも同じ実装です。各索引は列の値と行アドレスのポインタの組を持っています。列の値が一意かつ非NULLであればどの列の索引でもプライマリ・キー制約の索引になることができます。どの列の索引も同じ実装であるため、どの列がクエリーの検索条件に指定されてもアクセスするコスト、つまり処理時間は基本的に同等です。
[*2] Oracle Databaseの通常の表
また他のケースでは、プライマリ・キー列は表の作成時に指定が必須で、2次索引と呼ぶプライマリ・キー以外の列に作成した索引は、列の値とプライマリ・キー列の値の組を保持する実装になっているものがあります。2次索引をたどって表の行にたどり着くのに、プライマリ・キー列の索引をたどることになります。そのため、クエリーがプライマリ・キー列かそれ以外の列を検索条件に指定するかで、データにアクセスするコスト、つまり処理時間が異なります。
このケースの1つにクラスタリング索引と呼ばれる構造があります。これは、プライマリ・キー列の索引のリーフ・ブロックに、プライマリ・キー列の値と行アドレスの組合せの代わりに行そのものを格納する構造[*3]です。索引ブロックから表ブロックへのポインタ経由のアクセス1回分を省略することができます。
[*3] Oracle Databaseでは索引構成表(Index Organized Table)という。MySQL InnoDBのクラスタ・インデックス。
クラスタリング索引はプライマリ・キー列の索引とそれ以外の列の2次索引の扱いが明らかに異なります。クエリーがプライマリ・キー列を指定してアクセスする場合はプライマリ・キー列の索引を使用して、ヒープ表と索引の組み合わせよりもほんの少しだけ高速に行データにアクセスできます。しかし減少するのは索引ブロックから表ブロックをたどる1ホップであり、その効果は微々たるものです。プライマリ・キー以外の列の探索は2次索引とプライマリ・キー索引のブロックを複数ホップたどる必要があり、ヒープ表の場合よりも時間がかかってしまいます。
クラスタリング索引は2次索引の実装にさまざまな制約があり、Oracle Databaseではクラスタリング索引(索引構成表)が使用されることはほぼありません。その代わり通常のヒープ表を使用します。Oracle Databaseのヒープ表の索引の場合は、どの列に作成した索引も特別扱いするものがないというのが特徴です。