「RDBの感覚で物理設計をサボるな。階層型DBMSにおける『物理配置の乱れ』は、即座にシステムの死を意味する」
これは、私が大規模なミッションクリティカル・システムを救済する現場で、何度も繰り返してきた言葉だ。
リレーショナルデータベース(RDB)の世界では、データの物理的な格納位置はDBMSのストレージエンジンやオプティマイザのブラックボックスの裏に隠され、エンジニアは論理モデルとインデックスの設計に集中すれば事足りることが多い。しかし、ミリ秒以下の極限の応答速度が求められるメインフレームや超高速データ処理基盤で現役として君臨し続ける階層型DBMS(Hierarchical DBMS)においては、その常識は一切通用しない。
階層型DBMS(例えばIBMのIMS DBに代表されるアーキテクチャ)において、論理設計と物理設計は不可分であり、セグメントの物理配置こそがパフォーマンスのすべてを決定する。
今回は、階層型DBMSの心臓部である「セグメントのクラスタリング」と「オーバーフロー領域の管理」に焦点を当て、I/O負荷を極限まで低減するための物理設計の奥義を伝授する。
—
1. 階層型における「物理配置」が性能を支配する理由
RDBはテーブル同士を「JOIN(結合)」という論理操作で動的に結びつける。一方、階層型DBMSは、ルート(Root)セグメントから子(Child)セグメントへと、あらかじめ定義された物理ポインタ(Pointer)を辿ってデータにアクセスする。
[ルートセグメント: 顧客 (Customer)]
│
├─► [子セグメント: 注文 (Order)] ──► [孫セグメント: 明細 (Detail)]
│
└─► [子セグメント: 住所 (Address)]
このポインタを辿る際、もし親セグメントと子セグメントがディスク上の全く異なる物理ブロックに分散して格納されていたらどうなるか?
ポインタを1つ進めるたびに、ディスクのランダムI/O(シーク動作)が発生する。これでは、どれほど高速なCPUやメモリを積んでいても、ディスクI/Oのボトルネックによってシステムは完全に沈黙する。
目標はただ一つ。「1回の物理I/O(1ブロックの読み込み)で、関連する親子セグメントを可能な限りメモリ上(バッファプール)に一括して引き揚げること」。これこそが、物理データ配置の最適化における至高のテーゼである。
—
2. セグメント・クラスタリングの極意:物理的近接の設計
セグメントのクラスタリング(Clustering)とは、親子関係にある、あるいは頻繁に同時にアクセスされるセグメント同士を、物理的に同じブロック(またはControl Interval: CI)に近接して配置する技術だ。
これを実現するために、階層型DBMSではデータベース記述言語(DBD: Database Description)を用いて、物理的なデータ格納構造を厳密に制御する。
2.1 階層シーケンス(Hierarchical Sequence)と物理ブロックサイズ
階層型DBMSは、データを「前順深さ優先探索(Pre-order Depth-First Search)」の順序で物理的に格納しようとする。
1. ルートセグメント
2. 最左の子セグメント
3. そのさらに子セグメント(孫)
4. 隣の兄弟セグメント…
この順序でデータが隙間なく物理ブロックに詰め込まれるのが理想である。
ここで、物理ブロック(またはCI)のサイズ設計が極めて重要になる。
- ブロックサイズが小さすぎる場合: 親セグメントと子セグメントが別ブロックに泣き別れになり、I/O回数が増加する。
- ブロックサイズが大きすぎる場合: メモリ(バッファ)の消費量が無駄に増え、かつ、同一ブロック内での競合(ロック競合など)を招く。
標準的なオンライン処理(OLTP)においては、1つの「データベース・レコード(1つのルートとその配下の全セグメントの集合)」の平均的な合計サイズを算出し、その平均サイズの1.5倍から2倍程度をカバーするブロックサイズ(例:4KB、8KB、あるいはOSAM/VSAMの特性に合わせたサイズ)を選択するのが鉄則だ。
—
3. オーバーフロー領域の管理:パフォーマンス劣化の元凶を封じ込める
初期構築時には完璧にクラスタリングされていたデータベースも、日々の運用(データの追加・更新・削除)によって必ず劣化する。特にセグメントの追加(Insert)は、物理配置の調和を破壊する最大の要因だ。
親セグメントが格納されている物理ブロックに、新しく追加された子セグメントを格納する空きスペース(Free Space)がない場合、DBMSはその子セグメントを「オーバーフロー領域(Overflow Area)」という別系統の物理領域に退避させ、そこへポインタを繋ぐ。
【初期状態:完璧なクラスタリング(同一ブロック内)】
[ Block 001 ]───────────────────────────────────────┐
│ [Root: 顧客A] ──► [Child: 注文A-1] ──► [Child: 注文A-2] │ (I/O数 = 1)
└───────────────────────────────────────────────────┘
【劣化状態:空き容量不足によりオーバーフロー発生】
[ Block 001 (一次領域) ]─────────────────────────────┐
│ [Root: 顧客A] ──► [Child: 注文A-1] ──► (Pointer) ──┼──┐
└───────────────────────────────────────────────────┘ │ (I/O数 = 2に悪化)
│
[ Block 999 (オーバーフロー領域) ]◄─────────────────────┘
│ [Child: 注文A-2 (新規追加)] │
└───────────────────────────────────────────────────┘
このオーバーフロー領域へのジャンプ(ディスクアームの移動)こそが、I/O負荷を激増させる「サイレントキラー」である。これに対抗するための設計手法が以下の2点だ。
3.1 フリースペース(Free Space)の戦略的配置
スキーマ定義(DBD)において、初期ロード時に各物理ブロック内にどれだけの「余白」を残しておくかを明示的に設計する。
- `FREE BLOCK`(FBLOCK): 何ブロックに1ブロックを完全に空きブロックとして残すか。
- `FREE SPACE`(FSPACE): 各ブロック内に何パーセントの空き領域(パディング)を確保するか。
頻繁に子セグメントが追加されるルートの配下では、FSPACEを `20%`〜`30%` と高めに設定し、追加データが一次領域(Primary Area)内の同一ブロックに収まるように誘導する。
3.2 ルート・アンカー・ポイント(RAP)とハッシュ衝突の抑制
ランダムアクセス方式(HDAMなど)を採用する場合、ルートセグメントを格納するアドレスをハッシュ関数で決定する。このとき、同じブロックに複数のルートが集中する「ハッシュ衝突」が発生すると、これまたオーバーフローチェーンが形成される。
衝突を回避するために、ブロックごとに配置するRAP(Root Anchor Point)の数を最適化する。通常、1ブロックあたりの期待されるルートセグメント数と同等、あるいはそれ以上のRAPを確保し、物理的な分散配置を均等化する。
—
4. 物理データ配置を制御するスキーマ定義(DBD)の実践例
では、実際の設計において、これらがどのように定義されるのか。以下に、物理配置とポインタ制御を最適化したDBD(Database Description)の設計例を示す。
これは、顧客(Customer)とその注文(Order)の階層関係を、ポインタの局所性を高め、オーバーフローを抑制するように設計したメタルレベルの構成定義である。
====================================================================
- DATABASE DESCRIPTION (DBD) – HIGH-PERFORMANCE PHYSICAL DESIGN
====================================================================
DBD NAME=CUSTDB, X
ACCESS=(HDAM,VSAM), X
RMNAME=(DFSHDC40,3,100,800)
- ▲ ハッシュモジュール: DFSHDC40 (標準ハッシュ)
- RAP数: 3 (1ブロックあたり)
- 最大アドレスブロック数: 100
- 最大バイト数制限: 800バイト (これを超えるセグメントはオーバーフローへ)
——————————————————————–
- PHYSICAL DATASET DEFINITION (物理データセット定義)
——————————————————————–
DATASET DD1=CUSTDD1, X
DEVICE=3390, X
BLOCK=(4096), X
FRSPC=(20,5)
- ▲ BLOCK: 4KB (オンライン処理に最適なI/Oサイズ)
- FRSPC=(20,5): 初期ロード時に各ブロックの20%を空き領域とし、
- さらに5ブロックに1ブロックを完全にフリーブロックとして残す。
- これにより、後続の注文(ORDER)セグメント追加時のオーバーフローを徹底防御。
——————————————————————–
- SEGMENT DEFINITIONS (セグメント定義)
——————————————————————–
- 1. ROOT SEGMENT: CUSTOMER (顧客ルート)
SEGM NAME=CUSTOMER, X
BYTES=150, X
FREQ=50000, X
PARENT=0, X
PTR=(T)
- ▲ PTR=(T): TWIN FORWARD ポインタのみを保持。
- 双方向ポインタ(TB)は更新時のオーバーヘッドが大きいため、
- 参照主体、または一方向の追加のみであれば片方向ポインタでI/Oを節約する。
FIELD NAME=(CUSTID,SEQ,U),BYTES=10,START=1,TYPE=C
- 2. CHILD SEGMENT: ORDER (注文履歴 – 頻繁に追加が発生)
SEGM NAME=ORDSEG, X
BYTES=100, X
FREQ=250000, X
PARENT=((CUSTOMER,SNGL)), X
PTR=(CP,T)
- ▲ PARENT=((CUSTOMER,SNGL)): 親への物理ポインタを1つに絞る。
- PTR=(CP,T): Physical Child (CP) と Physical Twin (T) を使用。
- これにより、同一顧客の注文履歴が物理的に同じブロック内にチェーンされ、
- インデックスを経由せずに高速に連続スキャンが可能になる。
FIELD NAME=(ORDID,SEQ,U),BYTES=12,START=1,TYPE=C
FIELD NAME=(ORDDATE),BYTES=8,START=13,TYPE=C
DBDGEN
FINISH
END
この設計の意図(コードレビュー解説)
1. `RMNAME=(DFSHDC40,3,100,800)` の制限値 `800`:
ルートセグメントをハッシュで配置する際、1回のI/Oで読みたい範囲を最大800バイトに制限している。これにより、1つのルートの下に巨大なデータがぶら下がって初期配置ブロックを食い潰すのを防ぎ、他のルートのクラスタリング領域を保護している。
2. `FRSPC=(20,5)` のダブルセーフティ:
オンラインで秒間数百件の注文(`ORDSEG`)が追加されるシナリオを想定している。20%のブロック内空き領域(FSPACE)があるため、追加された注文データは、親である `CUSTOMER` と全く同じ物理ブロック(4KB)の余白に吸い込まれる。ディスクI/Oは「実質ゼロ(すでにメモリ上にあるブロックへの書き込みのみ)」で完結する。
—
5. パフォーマンス上の注意点と「設計の黄金律」
この設計を維持し、本番稼働後にシステムを死滅させないために、テクニカルリードとして以下の3つの鉄則を課す。
① ポインタの「ミニマリズム」を貫け
「念のため、逆方向ポインタ(`PTR=TB` や `PTR=LT`)も定義しておこう」という安易な妥協は許さない。
双方向ポインタは、セグメントの削除や挿入時のポインタ繋ぎ替え処理において、書き込み対象の物理ブロックを倍増させる。参照要件を徹底的にプロファイリングし、必要最小限の一方向ポインタだけで設計を構成せよ。
② 再編成(Reorg)の「限界値」を監視せよ
どんなに完璧なフリースペース設計を施しても、長期間の運用でいつかは限界に達し、オーバーフロー領域への退避(スプリット)が発生し始める。
運用監視において、「オーバーフロー・エリアへのアクセス比率(またはシーク回数)」を重要KPIとして監視せよ。
この比率が閾値(一般的にはデータベース全体の5%以上が断片化した場合)を超えたら、即座にデータベースのアンロード(Unload)およびリロード(Reload)による「再編成ユーティリティ」を実行し、物理配置の初期秩序を取り戻さなければならない。
③ 物理的なディスク配置(DASDボリューム)の分散
物理データセット(VSAM/OSAM)を切り分ける際、一次領域(Primary)とオーバーフロー領域(Overflow)を、ストレージシステム上の異なる物理チャネル、あるいは異なるSSD/HDDボリュームに配置せよ。万が一オーバーフローが発生した場合でも、物理的なI/O競合(ヘッドのシーク競合)をハードウェアレベルで緩和するためだ。
—
結び:アーキテクトとしての矜持
階層型DBMSは、現代のRDBやNoSQLに比べて「不自由」に見えるかもしれない。しかし、その不自由さと引き換えに得られるのは、ハードウェアの限界値に挑む極限のI/Oパフォーマンスである。
「物理構造を完全に掌握し、1回のディスク回転、1回のシーク動作をコントロールする」
この執念とも言える設計思想こそが、数十年を経てもなお、世界最速のトランザクション処理を支え続ける階層型DBMSの真髄なのだ。論理モデルの美しさに逃げるな。物理配置の細部にこそ、神(そして悪魔)は宿る。
コメント