Q 質問 RDBMSを使ったシステムで,条件カラムにインデックスを付けましたが検索時間はあまり変わりません。なぜでしょうか。

A 回答 インデックスは必ず使われるわけではありません。また,使っても必ず検索時間が短くなるとは限りません。


 「WHERE a = 10」のような検索条件をもつSQL文の実行では,カラムaにインデックスを付ければ,多くの場合は検索時間が短くなります。インデックスを利用することでディスクからメモリーに読み込むレコード数が減り,ディスクI/Oを削減できるからです。

 ただし,条件カラムにインデックスを付けても,検索時間が短縮されないケースがあります。主な理由としては,付けたインデックスが使われていない,インデックスを使っているが検索時間を短くするほどの効果が出ていない――の2つが考えられます。

使われないインデックス

 条件カラムに付けたインデックスは,必ずしも使われるとは限りません。実は,インデックスを使うかどうかの判断はRDBMSの「オプティマイザ」と呼ばれる機構が行っています。

 オプティマイザは,クライアントから送られてきたSQL文を解析し,最適な処理手続きを決めるものです。この手続きを「実行計画」と呼びますが,実行計画の策定時にインデックスを使うかどうかを判断します。

図1●インデックスを利用するかしないかはオプティマイザが判断する
インデックスを付ければ必ず利用されるわけではない。使えるのかどうか,また,使うと効果があるのかどうかをオプティマイザが判断する
 
図2●使われないインデックスの例(Oracle8iのマニュアルを参考に作成した)
検索条件のカラムにインデックスを付けるのが基本である。だが,図中のようなSQL文を記述するとインデックスは使われない
 その判断は基本的に2段階で行います。(1)使えるインデックスがあるか,(2)インデックスを使うと速くなると予測できるか――です(図1[拡大表示])。なお,オプティマイザには,あらかじめ決められたルールに基づいて実行計画を策定するルール・ベース・オプティマイザと,データベースの状態によって実行計画を策定するコスト・ベース・オプティマイザの2種類がありますが,ここでは現在主流のコスト・ベース・オプティマイザについて説明します。

 (1)の「使える」の意味は,インデックスが付けられているかどうかだけではありません。付けていても,図2[拡大表示]のようなSQL文では,ほとんどの場合インデックスは「使えない」と判断されます。このようなSQL文ではインデックスの効果が小さいことが分かっているからです。どのような条件だとインデックスを使わないかは,多少はRDBMS製品に依存する部分がありますが,多くは共通しています。

 つまり,SQL文によっては条件カラムにインデックスをいくら付けても,使われません。注意が必要なのは,書き方を変えるだけでインデックスが使えるようになるケースがあることです。例えば図2(5)は,「column1 < 1000」とすればcolumn1のインデックスが使われるようになります。

 図2は1インデックスに1カラムの「単一インデックス」の場合ですが,1インデックスにN個のカラムを含んだ「複合インデックス」の場合は,さらに複雑です。具体的には,カラム1,2,3の順で複合インデックスを作っている場合,カラム1が検索条件に含まれていなければインデックスは使わないなど,複合インデックス内のカラムの順番が大きく影響します。

 図1(1)をクリアしても,同(2)で引っかかるケースもあります。例えば“男”と“女”の2種類のデータしかありえないカラムに付けたインデックスは,それを使っても検索対象レコードを大幅に絞り込むことができません。場合によってはインデックスを読み込む分,ディスクI/Oが増えることもあります。このような効果の小さいインデックスは,使われないのです。効果の予測は,データベースの統計情報を基にオプティマイザが行います。

図3●インデックスは,検索時間の一部しか短縮しない
検索処理の時間は,構文解析や四則演算,ジョイン処理,ソート処理,ディスクI/Oの処理時間に依存する。インデックスは,「検索対象のレコードをメモリーに読み込む」時間を短くすることはできるが,その他の処理時間は短縮しない

インデックスは万能ではない

 オプティマイザがインデックスを使うと判断しても,検索時間がたいして短くならないこともあります。

 確かにインデックスを使えばディスクI/Oが減ります。しかし,そもそも全体の検索時間の中でディスクI/Oにかかる時間が占める割合が小さければ,焼け石に水です。具体的には,ソート処理を延々とやるような検索処理では,やみ雲にインデックスを付けても効果は小さいです(図3[拡大表示])。

 CPUやメモリー,ディスクI/Oの状態を見て,CPUとメモリーの負荷が高い場合は,まずは,それらの増設を考えるべきでしょう。インデックスを考えるのは,その次です。なお,CPUやメモリー,ディスクI/Oの状態は,Windows NT Serverであれば,OSの機能である「パフォーマンス・モニター」で確認できます。

(本誌)