インデックスの迷宮を制す:HIDAMプライマリインデックスの物理構造と極限チューニング
おい、設計レビューの真っ最中だが、ちょっと手を止めてくれ。
お前らが今描いているそのデータ構造、本当に数千万件のトラフィックに耐えられるか? リレーショナルデータベースの「インデックス=B+樹木構造」という常識をそのまま階層型DBMS(IMSなど)に持ち込もうとして、痛い目を見るエンジニアを私は数え切れないほど見てきた。
階層型DBMSの世界、特にHIDAM(Hierarchical Indexed Direct Access Method)におけるプライマリインデックスの物理構造は、RDBのそれとは根本的に思想が違う。ポインタの迷宮であり、ミリ秒単位のIOPSを削り出すための執念の塊だ。
今回は、HIDAMのプライマリインデックスが内部でどう構築され、データセグメントとどう結びついているのか。その物理構造の真実と、実務で絶対に踏み抜いてはならない設計パターンを叩き込む。心して読め。
—
1. HIDAMプライマリインデックスの物理構造:なぜ「木」が2つあるのか
まず大前提として、HIDAMは「シーケンシャルアクセス(HSAM/HIDAMのH部分)」の限界を打破するために生まれた。ルートセグメントを直接引き当てるためのプライマリインデックス(Primary Index)と、実際のデータが格納されるデータセット(E-DSG: Extent Data Set Group)が完全に分離されているのが最大の特徴だ。
ここで勘違いしやすいのが、「インデックスもデータも同じツリー構造なのだろう」という思い込みだ。違う。
- プライマリインデックス(VSAM KSDSとして実装): ルートセグメントを引くための単一階層の索引構造(実体はB-Treeに近いVSAMのKSDS)。
- データセグメント(VSAM ESDSとして実装): 実際の階層構造(ルートの下に子、孫ぶら下がる)を持つネットワーク/階層構造。
インデックス側は、データ側の複雑な階層構造など知ったことではない。「どのルートキーが、データ側のどこ(RBA: Relative Byte Address)にあるか」の対応表に特化している。
インデックスセグメントの内部構造
プライマリインデックスの最小単位は、インデックスセグメント(Index Segment)だ。
論理的には以下の要素で構成されている。
+——————-+———————–+
| インデックスキー | ターゲットRBAポインタ |
| (Root Key) | (Direct Address) |
+——————-+———————–+
このインデックスエントリが、VSAM KSDSのシリンダ/コントロール・インターバル(CI)の中に高密度に詰め込まれる。
—
2. データセグメントへのポインタ保持方法:物理RBAとダイレクトポインタの呪縛
ここが本日のハイライトだ。インデックスからどうやってデータセグメントのルートにたどり着くのか。
リレーショナルデータベースであれば、プライマリキーで引いた後にクラスタインデックス経由でブロックを探すが、HIDAMではインデックスセグメントが保持する「RBA(Relative Byte Address:相対バイトアドレス)」、あるいは高次な環境では「DBR(Direct Block Reference)」を用いて、データ側のESDS(Entry-Sequenced Data Set)上の物理位置を直接直撃する。
ポインタ解決のメカニズム
1. アプリケーションが `GU (Get Unique)` 呼出しを発行し、特定のルートキーを指定する。
2. DBMSはHIDAMのプライマリインデックス(KSDS)を索引探索し、該当するキーのエントリを見つける。
3. エントリに格納されている RBA(例: `0x00A34F20`) を取得する。
4. そのRBAをダイレクトに使い、データセット(ESDS)の該当物理ブロックへダイブする。
[ Application ]
│ (GU: Key = “007”)
▼
+──────────────────────────────+ RBA “0x00A34F20” +──────────────────────────────+
│ HIDAM Primary Index (KSDS) │ ───────────────────────> │ Data Segment (ESDS) │
│ [Key: 007 | RBA: 0x00A34F20]│ │ [Root Segment: 007] │
+──────────────────────────────+ │ └─> [Dependent Segment] │
+──────────────────────────────+
この「ダイレクトに物理アドレスを引く」構造ゆえに、恐ろしい副作用が存在する。それがデータの再配置(Reorganization)に伴うポインタの全更新だ。
—
3. 現場で血を流さないための設計パターン
この物理構造を踏まえ、お前たちが設計レビューで必ず守らなければならないルールを提示する。
設計アンチパターン:高頻度な可変長セグメントの更新
データセグメント側でルートや高頻度アクセスされる依存セグメントのサイズが頻繁に拡大・縮小するとどうなるか。
ESDS上のデータが溢れ、オーバーフローブロックへのチェインが発生する。最悪の場合、RBA自体が変わり、インデックス側のポインタが無効化、あるいは再配置バッチ(Reorg)の頻度が跳ね上がる。
> 【チーフアーキテクトの戒め】
> 「インデックスのキー長は最小限に絞れ」。
> HIDAMのプライマリインデックスのキーが肥大化すると、KSDSのコントロール・インターバル(CI)あたりのエントリ数が減り、インデックスの階層深度(Levels)が深くなる。結果、ルートに辿り着くまでのIOPSが無駄に消費される。キーには意味のない連番やサロゲートキー的なコンパクトな値を選ぶのが、極限のパフォーマンスを引き出す定石だ。
—
4. パフォーマンスチューニング:極限のIO削減戦略
最後に、HIDAMプライマリインデックスを運用する上で、プロフェッショナルなら知っておくべきチューニングの急所を授ける。
1. VSAM KSDSのCIサイズ(Control Interval Size)の最適化
インデックス側のVSAM KSDSのCIサイズは、ハードウェアのページサイズ(通常4KB、あるいは現代のストレージであればアライメントを考慮したサイズ)の倍数、あるいは効率的に収まるサイズに厳密に計算しろ。中途半端なサイズにすると、バッファプール(BFPOOL)のヒット率が劇的に落ちる。
2. インデックスバッファの独立プーリング
データ用のバッファプールと、HIDAMプライマリインデックス用のバッファプールは絶対に分離しろ。インデックスは常にメモリ上に常駐させたい(Pinned)。データスキャンによってインデックスのキャッシュが追い出される(キャッシュ汚染)ような設計は、アーキテクト失格だ。
3. フリースペース(FSPC)の適切な配分
インデックスの挿入・削除が頻繁なワークロードでは、KSDSのCI/CA(Control Area)に適切なFSPC(Free Space)を確保しろ。リビルドの頻度を最小限に抑えるためのバッファゾーンが必要だ。
—
総括
階層型DBMSのHIDAMプライマリインデックスは、黒魔術ではない。ハードウェアの物理アドレス(RBA)とインデックス(KSDS)を極限までリニアに結びつけた、先人たちの執念の結晶だ。
RDBの抽象化された世界に毒された頭のままでは、この構造の妙味は理解できず、システムは必ず重荷にあえぐことになる。
「どこにデータがあり、どうやってポインタを辿るのか」——この物理的なイメージを常に脳内に描きながら、コードとスキーマを組み上げろ。
次のレビューでは、インデックスのCIサイズとバッファ設計の根拠を数値で説明できるようにしておけよ。解散!
コメント