今回注目するのは,Bツリー・インデックスのマイナス面です。

 まず,デメリットを押さえておきましょう(図1)。インデックス・データのサイズは小さいとはいえ,データとしてディスクに格納されます。インデックス・データのために,ディスク領域を用意しておくことが必要です。そのほかインデックスは,更新処理を遅くします。インデックスを付けたカラムが更新されると,そのカラムのインデックスの更新が必要になるからです。インデックスを付けるだけでこれだけのデメリットが生じます。

図1●インデックスのデメリット
図1●インデックスのデメリット
インデックスはルート,ブランチ,リーフの3層構造(右)で,それぞれ別々のブロックに格納される(左)。主なデメリットは図示した2点  [画像のクリックで拡大表示]

 デメリットがあるので,インデックスをやみ雲に付けてはいけません。また,効果の得られないインデックスを付けると,デメリットだけが生じることになります。実際,インデックスを付けても効果の得られないケースはあります。

「性別」カラムに付けても効果なし

 この特集で使用しているサンプルの[顧客]テーブル(表1)で考えて見ましょう。

表1●[顧客]テーブルのカラム値
表1●[顧客]テーブルのカラム値

SELECT 顧客名 FROM 顧客 WHERE 性別 = 1 AND 地域 = ’関西’
意味:[性別]の値が1(女性)で,かつ,[地域]の値が関西である[顧客名]を抽出

 というSQL文があったとします。この特集では説明を分かりやすくするため,[顧客]テーブルは10ブロックに格納されていると想定しています。インデックスがなければディスク・アクセスが10回発生するので,その回数を減らすために,新たにインデックスを付けたとします。

 インデックスは検索条件の一つのカラムに付けるのが基本です。このSQL文では[性別]と[地域]の二つのカラムが検索条件になっていますので,そのどちらかに付けることになります。ここでは,[性別]カラムにBツリー・インデックスを付けたとします。

 そのインデックスは図2のようになるでしょう。通常のBツリー・インデックスはルート,ブランチ,リーフの3層構造をしていますが,[性別]カラム値は0と1の2種類しかないので,ブランチはなく,リーフは二つになります。

図2●[性別]カラムに付けたインデックス
図2●[性別]カラムに付けたインデックス
[性別]カラムの値は0と1だけなので,3層構造にはならない。同じカラム値のレコードのポインタは一つのリーフに格納されるので,リーフは二つ。ブランチは存在せず,ルートがリーフを指す

 このSQL文を処理する場合,インデックスを使わない処理手続きと使う処理手続きが考えられます。インデックスを使わない処理手続きは,

<手続き1> ([顧客]テーブルの全レコードに当たる)10ブロックをデータ・バッファに読み込み,[性別]が1で,かつ[地域]が関西のレコードを判定し,該当するレコードの[顧客名]を抽出

 となります。図3と併せて見てください。処理性能を大きく左右するディスク・アクセスが10回行われていることを確認してください。

図3●インデックスを使わない処理手続き
図3●インデックスを使わない処理手続き

 一方の,インデックスを使う手続きは,

<手続き2> Bツリー・インデックスのルートとリーフをデータ・バッファに読み込む。リーフのポインタからレコードのブロックを読み込み,該当レコードを抽出

 となります。図4と併せて見てください。注目すべきディスク・アクセス回数は12回です。12回のうち,9回はレコード・ブロックのアクセス。レコード・ブロックは全部で10個ありますが,そのほとんどが対象になっています。

図4●インデックスを使う処理手続き
図4●インデックスを使う処理手続き

 9回とした理由は次の通りです。今回の検索条件にある[性別]カラムは,2種類(0と1)しか値の種類がありません。レコードをブロックに格納するとき,その並び順は不定で,同じ[性別]を集めて保管されるわけではありません。ここでは[顧客番号]順に3レコードずつブロックに格納されたと考えたところ,[性別]が1のレコードは,10ブロックのうち9ブロックに含まれていました。それゆえ,レコード・ブロックのアクセス回数を9回としました。

 手続き2のディスク・アクセスは12回となり,インデックスを使わない手続き1より回数が多くなりました。おそらく実行プランとして手続き1が選ばれるでしょう。つまり,インデックスを使ったにもかかわらず,効果を得られなかったというわけです。

 この例から言えることは,値の種類が少ないカラムにインデックスを付けても効果は得られない,ということです。[性別]のように2種類しかないデータはその典型ですが,[地域]カラムも値の種類は9種類しかなく,効果を得にくいカラムと言えそうです。

 今回はBツリー・インデックスに絞って説明していますが,インデックスの種類によっては,値の種類数が少なくても効果があります。[性別]カラムや[地域]カラムに付けて効果があるのは,「ビットマップ・インデックス」です。ここでは詳しく説明しませんが,値の種類数が少なければどんなインデックスでも効果がない,というわけではありません。

監修:藤塚 勤也(ふじづか きんや) NTTデータ 基盤システム事業本部 オープンソース開発センタ 技術開発担当 シニアスペシャリスト
沖電気工業,タンデムコンピューターズ(現日本HP)を経て,2003年より株式会社 NTTデータに勤務。現在は,オープンソース・ソフトウエアを活用したエンタープライズ・システム向けの技術開発・技術支援に従事しており,特にシステムの中核であるRDBMSに注力している。「RDBMS解剖学」(翔泳社)を共著