【実務・中級編】 論理親子関係 – 階層型DBMS

階層型DBMSの深淵:論理親子関係(Logical Parent-Child)がもたらす物理の呪縛からの解放

こんにちは。チーフアーキテクトの私だ。
今日のコードレビューで、また「親をどこに持たせるべきか」という不毛な議論を見かけた。
リレーショナルデータベース(RDB)に毒された頭脳では、JOINの幻想に囚われ、データの物理配置とポインタの重みを見落としがちになる。

現代のエンジニアから見れば、IBMのIMSに代表される「階層型DBMS(Hierarchical DBMS)」はレシックな遺物に映るかもしれない。だが、データ構造の本質――「アクセスパスの最適化と整合性の担保」において、階層型が到達した境地はいまだに色褪せていない。

今回は、その階層型DBMSにおける最も洗練されていながら、同時に取り扱いを誤るとシステムを崩壊させる禁断のメカニズム「論理親子関係(Logical Parent-Child)」について、実務の現場で使える極限の知見を授けよう。

—

1. なぜ「物理」だけでは足りないのか?

階層型DBMSの基本は、ツリー構造だ。親セグメントの下に複数の子セグメントがぶら下がり、ポインタチェーンによって物理的に連続して配置される。この構造の最大の武器は「圧倒的なI/O効率」にある。親をヒットすれば、子はすぐ隣(あるいは同一シリンダ上)にいる。

だが、現実世界のデータは綺麗な一本のツリーには収まらない。

  • 顧客(Customer)ツリーの下にある注文(Order)。
  • 別の場所にある、商品(Product)マスター。

「ある注文がどの商品を指しているか」を表現したい時、もし商品を「注文の子」として物理的に従属させたらどうなるか?
商品データが注文の数だけ重複して物理格納されるか、あるいは顧客ツリーの枠組みを超えた複雑な物理ポインタの迷宮を作り出すことになる。更新のたびに地獄を見るのは明白だ。

ここで登場するのが、異なる物理データベース(DB)に存在するセグメント間を繋ぐ架け橋、「論理親子関係」である。

—

2. 論理親子関係のメカニズム:論理親と論理子

論理親子関係(LPC)は、物理的な階層の制約をバイパスし、異なるデータベース定義(DBD)間を論理的に結ぶ機能だ。

  • 論理親(Logical Parent: LP): 参照される側のセグメント(例:商品マスターDBの `PRODUCT` セグメント)。
  • 論理子(Logical Child: LC): 参照する側のセグメント(例:注文DBの `ORDER_ITEM` セグメント)。

重要なのは、論理子は物理的には「注文DB」の物理親(この場合は `ORDER` セグメント)に従属しているが、同時に「商品DB」の論理親を指し示すポインタを持っているという点だ。

概念スキーマのイメージ(DDL風記述)

IMS DBD/PSB定義を現代のエンジニア向けに抽象化したDDLで表現してみよう。

— データベース定義 1: 商品カタログ物理DB (PRODDB) —
DBD NAME=PRODDB
SEGM NAME=PRODUCT,BYTES=100 # 商品セグメント(論理親になり得る)
FIELD NAME=PROD_ID,SEQ,BYTES=10

— データベース定義 2: 注文管理物理DB (ORDERDB) —
DBD NAME=ORDERDB
SEGM NAME=CUSTOMER,BYTES=200 # 物理親:顧客
SEGM NAME=ORDER,BYTES=150,PARENT=CUSTOMER # 物理子:注文
FIELD NAME=ORD_ID,SEQ,BYTES=10
SEGM NAME=ITEM,BYTES=50,PARENT=ORDER # 物理子:注文明細(これが論理子になる)
FIELD NAME=PROD_REF,LCHILD=(PRODUCT,PRODDB) # ★ここで別DBの商品を論理親として指す

この定義により、`ITEM` セグメントは物理的には `ORDER` の子供でありながら、論理的には `PRODUCT` の子供として振る舞うことができる。これが論理親子関係の本質だ。

—

3. 実務で直面する「参照の仕組み」とエンジニアリングの罠

コードレビューでよくある誤解が、「論理親子関係は、RDBの外部キー(Foreign Key)と同じだろう」という安易な認識だ。
全く違う。 覚悟して聞いてほしい。RDBのFKは単なる値の制約だが、階層型のLPCは「物理的なポインタの埋め込み」である。

論理子の中身はどうなっているか?

ディスク上において、論理子セグメント(`ITEM`)の接頭辞には、論理親(`PRODUCT`)の物理アドレス(あるいはダイレクト・アドレス・ポインタ)がシステムによって書き込まれる。

アプリケーションが `ITEM` を経由して `PRODUCT` の情報にアクセスする場合、DBMSは以下の挙動をとる。
1. `ORDER` ツリーを辿り、`ITEM` を物理的にヒット。
2. `ITEM` に埋め込まれた論理親ポインタ(LPP)を読み取る。
3. ポインタを辿って、別DB(`PRODDB`)の該当 `PRODUCT` セグメントへダイレクトにジャンプする。

ここに潜むパフォーマンスの罠

RDBであれば、インデックススキャンやハッシュ結合で済む話だが、階層型DBMSでこれを乱用すると「ポインタ迷子」によるI/Oの嵐を引き起こす。

  • 双方向論理関係のコスト: 論理親側からも「誰から指されているか(論理双子ポインタ: Logical Twin Pointer)」を維持する必要がある場合がある。これがあると、商品を1件削除するだけで、それを指しているすべての注文明細(論理子)のポインタチェーンを巻き込んだカスケード更新が発生し、DBがロックアップする。

—

4. 堅牢な設計パターンとチーフアーキテクトからの戒め

では、この強力だが危険な「論理親子関係」を、我々はいかにして使いこなすべきか。設計レビューで私が必ず確認する3つの原則を授ける。

パターンA:参照専用(Read-Mostly)のマスター参照に限定せよ

論理親となるセグメント(商品や拠点など)が、「めったに更新されず、ひたすら参照される」性質を持つ場合にのみLPCを採用せよ。
逆に、頻繁にINSERT/DELETEが発生するトランザクションデータを論理親に据えると、ポインタのメンテナンスコストでシステムが窒息する。トランザクション間の関連は、極力同一物理DB内の階層(物理親子)で完結させるか、アプリケーション層でのID保持(緩い結合)に逃げよ。

パターンB:カスケード削除のルール(RULEパラメータ)を死守せよ

論理親が削除された時、論理子をどう扱うか。ここを曖昧にするとデータの整合性が一瞬で崩壊する。
定義時には必ず削除規則(RULE)を明示的に指定し、レビューで検証すること。

  • `RULE=VIRTUAL` / `LOGICAL`: 論理親が消えても論理子は残すが、ポインタは無効化(あるいはエラーを返す)。
  • `RULE=CASCADE`: 論理親の削除に伴い、論理子も強制削除。

実務では、誤ってマスタを消した瞬間に全顧客の注文履歴まで消え去る `CASCADE` の悪夢を避けるため、厳格なアプリケーション側の排他制御と組み合わせた設計が必須となる。

パターンC:物理ストレージの再配置(Reorganization)計画を怠るな

論理親子関係を多用したデータベースは、ポインタの参照先が異なるボリュームやシリンダにまたがるため、時間の経過とともにポインタの断片化(ストレージの劣化)が進行する。
「動いているから放置する」はエンジニアの怠慢だ。定期的なイメージコピーと、ポインタを再構築する再編成(Reorg)バッチの実行計画をアーキテクチャの初期段階で組み込んでおけ。

—

結びにかえて

階層型DBMSの論理親子関係は、物理的な制約という「重力」からデータを解放し、柔軟なネットワーク的表現を可能にする美しき機構だ。

しかし、その美しさは、ポインタとストレージ構造への深い理解という代償なしには手に入らない。RDBの抽象化された世界に慣れきったエンジニアよ、もう一度「データがディスク上でどう並び、どう指し示されているか」の原点に立ち返れ。

設計書を開き、その論理親のポインタの向こう側に何があるか、正確にイメージできないうちはコードを書く資格はない。
――さて、次のレビューに移ろうか。

コメント

タイトルとURLをコピーしました