Oracle Index の内部構造を徹底解説:B-tree、IOT、Bitmap Indexの仕組みと使い分け

はじめに

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

InnoDB、PostgreSQLに続く3本目です。OracleはBitmap IndexやIndex-Organized Table(IOT)など、独自のインデックス機能が豊富です。Oracle 19c / 23aiを中心に、以下を解説します:

  • Heap TableとIndex(PostgreSQLと同じ分離構造)
  • B-tree Indexの内部構造
  • Index-Organized Table(IOT):InnoDBのClustered Indexに相当
  • Bitmap Index:DWH向けの特殊インデックス
  • その他のインデックスタイプ

Heap TableとIndex

OracleのテーブルはPostgreSQLと同じくHeap構造がデフォルトです。レコードは挿入順に格納され、インデックスとは分離しています。

Oracle用語              InnoDB用語           PostgreSQL用語
──────────────────────────────────────────────────────────
Heap Table             Clustered Index      Heap
ROWID                  ―                    ctid
B-tree Index           Secondary Index      B-tree Index
IOT                    Clustered Index      ―

ROWID

PostgreSQLのctidに相当するのがROWIDです。行の物理位置を表します:

ROWID = OOOOOOFFFBBBBBBRRR
        ^^^^^^               データオブジェクト番号
              ^^^            相対ファイル番号
                 ^^^^^^      ブロック番号
                       ^^^   行番号
SELECT ROWID, employee_id, last_name FROM employees WHERE employee_id = 100;

ROWID              EMPLOYEE_ID  LAST_NAME
------------------ -----------  ---------
AAAEAeAAEAAAADNAAA         100  King

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

B-tree Index

OracleのB-tree IndexはPostgreSQLやInnoDBと基本構造は同じですが、いくつかの特徴があります。

ブランチブロックとリーフブロック

          [Branch Block]
          | Smith | Jones |
         /       |        \
  [Leaf Block] [Leaf Block] [Leaf Block]
  Adams,ROWID  Jones,ROWID  Smith,ROWID
  Brown,ROWID  King,ROWID   Taylor,ROWID
      ↔            ↔            ↔
  (リーフ同士が双方向リンクリストで接続)

NULLの扱い

OracleのB-tree Indexは全キーカラムがNULLの行をインデックスに含めません。これは重要な特徴です:

-- この検索はインデックスを使えない
SELECT * FROM employees WHERE commission_pct IS NULL;

-- 回避策:NULLでない定数を含む複合インデックス
CREATE INDEX idx_comm ON employees(commission_pct, 0);

InnoDBとPostgreSQLはNULLをインデックスに含めます。

Index Block構造

  • Block Header ブロック管理情報
  • Index Entry 1: [Key, ROWID]
  • Index Entry 2: [Key, ROWID]
  • Free Space
  • Row Directory 各エントリへのオフセット

TREEDUMP で内部構造を確認

ALTER SESSION SET EVENTS 'immediate trace name treedump level INDEX_OBJECT_ID';
----- begin tree dump
branch: 0x1400021 (block 33)
   leaf: 0x1400022 (block 34) keys 300
   leaf: 0x1400023 (block 35) keys 285
   leaf: 0x1400024 (block 36) keys 290
----- end tree dump

Index-Organized Table(IOT)

IOTとは

IOTはテーブルデータをB-tree Indexのリーフに格納する構造です。InnoDBのClustered Indexとほぼ同じ概念です。

CREATE TABLE sessions (
    session_id  NUMBER PRIMARY KEY,
    user_id     NUMBER,
    login_time  TIMESTAMP,
    data        VARCHAR2(200)
) ORGANIZATION INDEX;  -- ← これでIOTになる
通常のHeap Table + Index:
  Index Leaf: [session_id=1, ROWID] → Heap Block: [session_id=1, user_id=5, ...]
  (2回のI/O)

IOT:
  B-tree Leaf: [session_id=1, user_id=5, login_time=..., data=...]
  (1回のI/O)

IOTとInnoDBの比較

InnoDB Clustered Index Oracle IOT
デフォルト 常にClustered Index Heap Table(明示的にIOT指定が必要)
Secondary Index PK値を格納 Logical ROWID(推測ベース)
Overflow なし(全データがリーフ) OVERFLOW句で大きなカラムを別セグメントに

OracleでIOTが使われるのは、PK検索が主体のテーブル(セッション管理、ルックアップテーブル等)に限られます。InnoDBのように全テーブルがClustered Indexという設計とは対照的です。

Bitmap Index

OracleのBitmap Indexは他のDBにはない(PostgreSQLにはBRINがあるが別物)独自機能です。

Bitmap Indexとは

カーディナリティ(値の種類)が低いカラムに有効なインデックスです。各値に対してビットマップ(ビット配列)を持ちます:

gender カラムの Bitmap Index:

値 'M': 1 0 1 1 0 1 0 0 1 1  ← 各ビットが行に対応(1=該当)
値 'F': 0 1 0 0 1 0 1 1 0 0

ビットマップ演算

複数条件の組み合わせがビット演算で超高速に処理できます:

SELECT COUNT(*) FROM employees
WHERE gender = 'M' AND department = 'Sales';

-- 内部処理:
-- gender='M':      1 0 1 1 0 1 0 0 1 1
-- dept='Sales':    0 0 1 0 0 1 0 0 1 0
-- AND結果:         0 0 1 0 0 1 0 0 1 0  ← 3行が該当

制約

Bitmap IndexはDWH(データウェアハウス)向けです。OLTP環境では使えません:

  • 行レベルロックではなくビットマップセグメント単位のロック
  • 同時更新でロック競合が激しい
  • INSERT/UPDATE/DELETEが遅い
B-tree Index Bitmap Index
カーディナリティ 高い(ユニーク値が多い) 低い(性別、ステータス等)
複数条件の組み合わせ Index Merge(遅い) ビット演算(超高速)
同時更新 行レベルロック セグメントロック(競合大)
用途 OLTP DWH

まとめ

トピック InnoDB PostgreSQL Oracle
テーブル構造 Clustered Index Heap Heap(IOTも選択可)
主要インデックス B+Tree B-tree, GiST, GIN, BRIN B-tree, Bitmap, Function-based
NULLの扱い インデックスに含む インデックスに含む 全キーNULLは除外
並行制御 SX-latch Lehman-Yao ラッチ(ITL方式)
DWH向け なし BRIN Bitmap Index
Clustered構造 常に(デフォルト) なし IOT(明示指定)

次回はSQL Server Indexを同じ切り口で解説します。

参考文献

コメントする