この特集で使用する[顧客]テーブル(表1)を基に,インデックスの構造を具体的に考えて見ましょう。[顧客]テーブルは30レコードあります。このテーブルの[顧客番号]カラムにBツリー・インデックスを付けると,図1のようになります。説明を簡単にするために,ルートに含むカラム値は1個(ブランチは2個)にしていますが,実際はもっとたくさんのカラム値を含みます。

表1●[顧客]テーブル
表1●[顧客]テーブル

図1●[顧客]テーブルの[顧客番号]カラムに付けたインデックス
図1●[顧客]テーブルの[顧客番号]カラムに付けたインデックス
一つのルート(,ブランチ,リーフ)に含まれるカラム値は,実際はもっと多い。だが基本的に,レコード数が多くなっても構造は同じである  [画像のクリックで拡大表示]

 ここで,ルート,ブランチ,リーフに含むカラム値に着目してほしいのですが,ルート配下にある二つのブランチの一方は,ルートに含むカラム値以下の値,もう一方はルートに含むカラム値より大きな値になっています。ブランチとリーフの関係も同じです(二つのカラム値があり三つのリーフを指していますが,その構造は基本的に同じです)。

 単純な配列構造に比べると複雑に感じるかもしれません。なぜ,こうした構造になっているかを説明する前に,あるカラム値を持つレコードを見つけるまでの動きをたどってみましょう。カラム値1030のレコードを見つける場合を考えてみます。まずルートを読み取り,そこに含まれるカラム値から,次にブランチ2を読めばよいことが分かります。同様に,ブランチ2のカラム値から,次はリーフ6を読めばよいことが分かります。そしてリーフ6のデータから,顧客番号が1030のレコードのポインタを特定できます。ルート,ブランチ,リーフ,レコードをそれぞれ1回ずつ読むので,ディスク・アクセス回数は4回になります。

 サンプル・テーブルのようにレコード数が少ないなら,書籍の索引のように単純な配列構造の方が,ディスク・アクセス回数が少なくなるのではないか。そのように思われた読者もいることでしょう。確かに30レコードなら,単純な配列構造の方がディスク・アクセス回数は少なくなります。ですが,実際の業務アプリケーションでは,レコード数はもっと多くなります。インデックスのデータ(カラム値とポインタ)は,レコードそのものに比べればサイズは小さいですが,レコード数が増えれば比例して大きくなります。ということは,レコード数が増えれば(インデックスの)ディスク・アクセス回数も増えるということです。

 それに対してBツリー・インデックスは,レコード数が増えてもルート,ブランチ,リーフをそれぞれ基本的に1回ずつ読めばよく,ディスク・アクセス回数は一定になります。これが,樹木のような3層構造になっている理由の一つです。一定になるだけでなく,実業務で利用するデータベースを想定すると,Bツリー・インデックスのディスク・アクセス回数は,単純な配列構造に比べて少なくなると言えるでしょう。

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