Db2 Index の内部構造を徹底解説:B+Tree、MDC、カラムオーガナイズド表まで

はじめに

この記事では、IBM Db2のインデックスの内部実装を深掘りします。

シリーズ最終回です。Db2はMDC(Multi-Dimensional Clustering)やカラムオーガナイズド表など、独自のデータ配置最適化機能を持っています。Db2 11.5を中心に解説します。

テーブル構造とインデックス

Db2のテーブルはPostgreSQLやOracleと同じくHeap構造がデフォルトです。

Db2用語                 InnoDB用語           PostgreSQL用語
──────────────────────────────────────────────────────────
Regular Table          Clustered Index      Heap
RID (Record ID)        ―                    ctid
Index                  Secondary Index      Index
MDC Table              ―                    ―
Column-organized Table ―                    ―

RID(Record ID)

行の物理位置を表す識別子です:

RID = Page Number + Slot Number

インデックスのリーフにはキー値とRIDが格納されます。PostgreSQLのctid、OracleのROWIDと同じ仕組みです。

B+Tree Index

Db2のインデックスはB+Treeです(InnoDBと同じ名称)。

基本構造

          [Root Page]
          | 100 | 200 |
         /      |      \
  [Leaf Page] [Leaf Page] [Leaf Page]
  10,RID      100,RID     200,RID
  20,RID      120,RID     250,RID
  50,RID      150,RID     300,RID
     ↔           ↔           ↔

INCLUDE列

Db2もSQL ServerやPostgreSQLと同様にINCLUDE列をサポートします:

CREATE INDEX idx_name ON employees(name) INCLUDE (department_id);

-- このクエリはIndex-Only Accessで完結
SELECT name, department_id FROM employees WHERE name = 'Alice';

Db2では「Index-Only Access」と呼びます(SQL Serverの「Covering Index」、PostgreSQLの「Index Only Scan」に相当)。

オンラインインデックス再編成

-- オンラインでインデックスを再編成(サービス停止不要)
REORG INDEXES ALL FOR TABLE employees ALLOW WRITE ACCESS;

MDC(Multi-Dimensional Clustering)

Db2の最もユニークな機能がMDCです。

MDCとは

テーブルのデータを複数のカラムの値の組み合わせに基づいて物理的にクラスタリングします。

CREATE TABLE sales (
    sale_date  DATE,
    region     VARCHAR(20),
    product_id INT,
    amount     DECIMAL(10,2)
) ORGANIZE BY DIMENSIONS (sale_date, region);

仕組み:Block Index + Cell

MDCテーブルでは、ディメンションの値の組み合わせごとにCell(ブロックの集合)が作られます:

                    region=East    region=West
sale_date=2026-01  [Block1,Block2] [Block3]
sale_date=2026-02  [Block4]        [Block5,Block6]
sale_date=2026-03  [Block7]        [Block8]

各ディメンションにBlock Indexが自動作成されます。Block Indexは通常のB+Treeと違い、リーフが個々のRIDではなくBlock IDを指します:

通常のIndex:  key → [RID1, RID2, RID3, ...]     (行単位)
Block Index:  key → [Block1, Block2, ...]         (ブロック単位)

MDCの利点

-- この検索は region='East' のブロックだけスキャン
SELECT * FROM sales WHERE region = 'East';

-- 2つのBlock Indexの結果をビット演算で結合
SELECT * FROM sales WHERE region = 'East' AND sale_date = '2026-01-15';
  • ブロック単位のスキャンでI/Oが大幅に削減
  • 複数ディメンションの組み合わせ検索が高速
  • データの物理配置が自動的に維持される(INSERTで適切なCellに配置)

各DBのクラスタリング比較

InnoDB PostgreSQL Oracle SQL Server Db2
自動クラスタリング PK順(常に) なし なし Clustered Index順 MDC(多次元)
手動クラスタリング ― CLUSTER ― ― REORG
維持 自動 維持されない ― 自動 自動(MDC)

カラムオーガナイズド表(BLU Acceleration)

Db2 10.5で導入された列指向ストレージです。SQL ServerのColumnstore Indexに相当します。

CREATE TABLE sales_analytics (
    sale_date  DATE,
    region     VARCHAR(20),
    amount     DECIMAL(10,2)
) ORGANIZE BY COLUMN;

内部構造

Column Group 1: sale_date列  [2026-01-01, 2026-01-02, ...] (圧縮済み)
Column Group 2: region列     [East, West, East, ...]        (辞書圧縮)
Column Group 3: amount列     [100.00, 250.00, ...]          (圧縮済み)
  • Synopsis Table:各カラムの最小値/最大値を保持(Data Skipping用)
  • 辞書圧縮:カーディナリティの低いカラムに特に効果的

行指向 vs 列指向の選択

行指向(デフォルト) 列指向
OLTP(INSERT/UPDATE) ✅ 高速 ❌ 遅い
分析クエリ(集計) ❌ 全列読み込み ✅ 必要な列だけ読む
圧縮率 普通 高い(10x〜)
用途 トランザクション処理 DWH/分析

まとめ:インデックスシリーズ全体比較

トピック InnoDB PostgreSQL Oracle SQL Server Db2
テーブル構造 Clustered Index Heap Heap(IOT可) Clustered or Heap Heap(MDC/列指向可)
主要インデックス B+Tree B-tree, GiST, GIN B-tree, Bitmap B-tree, Columnstore B+Tree, Block Index
INCLUDE列 なし あり(11〜) なし あり あり
条件付きIndex なし Partial Index なし Filtered Index なし
NULLの扱い 含む 含む 全キーNULL除外 含む 含む
列指向 なし なし In-Memory Columnstore カラムオーガナイズド表
多次元クラスタリング なし なし なし なし MDC
DWH向け なし BRIN Bitmap Columnstore MDC + 列指向

5つのDBを比較すると:

  • InnoDB:Clustered Index一本のシンプルな設計。全テーブルがB+Tree
  • PostgreSQL:最も多様なインデックスタイプ(B-tree, GiST, GIN, BRIN, SP-GiST, Hash)
  • Oracle:Bitmap IndexとIOTが独自。NULLの扱いに注意
  • SQL Server:Columnstore Indexが強力。INCLUDE列とFiltered Indexの実用性が高い
  • Db2:MDCによる多次元クラスタリングが唯一無二。列指向ストレージも統合

参考文献

コメントする