【実務・中級編】 フリースペース管理と断片化対策 – 階層型DBMS

階層型DBMSの断片化防衛ライン:フリースペース管理と物理レイアウトの極意

おい、設計レビューの手を止めてくれ。
今、君が描いたこのスキーマ定義、そしてフリースペースのデフォルト値をそのまま放置しているコード。本番環境で1ヶ月走らせたら、確実にIOボトルネックでシステムが窒息する。

リレーショナルデータベース(RDBMS)のつもりで階層型DBMS(Hierarchical DBMS)を触ると、足元をすくわれる。ツリー構造のポインタチェイン、セグメントの物理的隣接性、そして可変長レコードの詰め込み――これらを理解せずして、高スループットな基幹系システムなど作れない。

今回は、階層型DBMSにおける「フリースペース管理(Free Space Management)と断片化対策」の核心を叩き込む。実務の現場で生き残るための設計パターンを共有しよう。

—

1. なぜ階層型DBMSで「断片化」が致命傷になるのか

RDBMSのB+Treeインデックスであれば、ページ分割(Page Split)が発生しても、ツリーの再バランスによって局所的な非効率性はある程度隠蔽される。しかし、純粋な階層型DBMS(IMSや一部の超高速組み込み型Hierarchical Storeなど)の世界では話が違う。

親セグメント(Segment)とその子セグメント群は、原則として物理的に連続した領域、あるいはポインタで緊密に結ばれたクラスタ領域に配置される。

[ 親セグメント: 顧客ID 001 ] —> [ 子セグメント: 注文1 ] —> [ 子セグメント: 注文2 (削除済・空き) ] —> [ 子セグメント: 注文3 ]

ここで何が起きるか?
子セグメントの「更新(特に可変長データの拡張)」や「削除・挿入」が頻発すると、セグメント間のパッキングが崩れ、ページ内に再利用できない細切れの空き領域(外部断片化)が生まれる。結果として、1つの論理的なレコード(根から葉までのパス)を読み込むために、ストレージヘッドがあちこちをシークする事態――「スラッシング」を引き起こすのだ。

—

2. フリースペースの予約設定(PCTFREE / FILLFACTOR の概念)

断片化を防ぐ唯一にして最大の防衛策は、「最初から余裕(余白)を持たせて配置する」ことだ。
階層型DBMSのDDLでは、セグメント定義時にブロック内、あるいはセグメント領域内の空き率を予約するパラメータ(多くのエンジンでは `PCTFREE` や `RESERVE_SPACE` と呼ばれる)が存在する。

これを適当にデフォルト値のままで運用している現場があまりに多い。挿入・更新のワークロードに応じた「正確な空き率の算出」をロジカルに行おう。

ワークロード別・フリースペース算出の方程式

空き率 $F$ は、以下の要素から導き出す。

$$F = \left( \frac{\text{平均更新サイズ増加量} \times \text{更新頻度}}{\text{初期レコードサイズ}} \right) \times 100 + \text{安全余裕係数}$$

具体的に、コードレビューで指摘すべき3つのパターンを見ていこう。

パターンA:イミュータブル・ログ型(挿入のみ)

  • 特徴: 過去のデータは変更されず、常に末尾への追加(Append Only)が発生する。
  • 設計指針: 更新がほぼ発生しないため、`PCTFREE 0`(または極小値)で十分。空き領域を空けることは、逆に物理密度を下げ、スキャンの効率を落とす。

パターンB:ヘビー・アップデート型(頻繁な可変長データの肥大化)

  • 特徴: 顧客のステータス変更や、JSON/XML等の可変長テキストフィールドが頻繁に更新され、サイズが拡大する。
  • 設計指針: `PCTFREE 25` 〜 `40` を強く推奨する。更新時にページ分割やオーバーフローレコードの発生を防ぐため、あらかじめ30%前後の余白をブロック内に残す。

パターンC:ハイブリッド・トランザクション型(挿入・削除がランダム発生)

  • 特徴: 子セグメントの削除と新規挿入が入り乱れる。
  • 設計指針: `PCTFREE 10` とし、後述する定期的な「セグメント・デフラグ(Re-pack)」のバッチを運用スケジュールに組み込む。

—

3. 実践:堅牢なスキーマ定義とフリースペース管理DDL

百聞は一見に如かず。実務で使える堅牢な階層型DBMSのDDL設計例を示す。

— =====================================================================
— スキーマ定義: 顧客(親)と 契約明細(子)の階層構造
— ターゲットワークロード: 契約明細の追加・可変長メモの更新が頻発
— =====================================================================

— 親セグメント: 顧客マスタ
CREATE SEGMENT TYPE CUSTOMER_SEGMENT (
CUSTOMER_ID CHAR(10) PRIMARY KEY,
COMPANY_NAME VARCHAR(100),
UPDATED_TIMESTAMP TIMESTAMP
)
— 親はマスターデータであり更新頻度が低いため、スペースを密に詰める
STORAGE (
BLOCK_SIZE 8192,
PCTFREE 5 — 読み込み効率を重視し、余白は最小限に抑える
);

— 子セグメント: 契約明細(顧客セグメントの配下に物理的・論理的に従属)
CREATE SEGMENT TYPE CONTRACT_SEGMENT
PARENT CUSTOMER_SEGMENT
POINTER IS SYMMETRIC (
— ツリー走査を高速化するためのポインタチェイン設定
CHILD_POINTER = FIRST_CHILD,
TWIN_POINTER = NEXT_TWIN
)
(
CONTRACT_ID CHAR(12) PRIMARY KEY,
CONTRACT_STATUS CHAR(2),
— 可変長メモ:後から文字数が急増するリスクあり
REMARKS VARCHAR(1000)
)
— 【重要】子セグメントは更新と挿入が激しいため、フリースペースを贅沢に確保
STORAGE (
BLOCK_SIZE 8192,
PCTFREE 35, — 更新時のデータ肥大化(Row Migration)を完全にブロックする
PCTUSED 60 — 領域が60%を下回るまで、再びINSERTの対象としない(断片化再発防止)
);

チーフアーキテクトからのコードレビューの視点

1. `PCTFREE 35` の意図を説明できるか?

  • レビューで「なんでこんなに空き領域を無駄にするんだ?」と聞かれたら、「可変長フィールド `REMARKS` の更新に伴う行マイグレーション(Row Migration)を防ぎ、物理的なI/Oを1パスに収めるためです」と即答できるようにしろ。ここをケチると、後日本番でDBアプライアンスのCPUがI/O待機で焼き切れる。

2. `PCTUSED` のチューニング

  • `PCTFREE` とセットで語られるのが `PCTUSED` だ。空き領域管理のヒステリシス(Hysteresis)を適切に設定しないと、ブロックが「空き・埋まり」を頻繁に繰り返し、かえってメタデータ管理のオーバーヘッドが増大する。更新頻度が高い子セグメントでは `PCTUSED 60` あたりが経験則として最も安定する。

—

4. 運用レイヤー:避けて通れない断片化対策とリパック手法

どれほど精緻に `PCTFREE` を設計しても、長期間の運用において階層型DBMSのデータ領域は徐々に汚れていく(断片化する)。

定期的なメンテナンスプロセスとして、以下のステップを運用の標準に組み込め。

1. 断片化率のモニタリング

  • データベースの統計情報(Catalog)から、ブロック内の平均空き容量と実データ量の乖離を常時監視する。
  • フラグメンテーション率が 25%を超えたセグメント を検知アラートの閾値とする。

2. オンライン/オフライン・リパック(Re-pack)の実施

  • 階層型DBMSの構造上、ツリー全体の物理的再配置にはコストがかかる。夜間のバッチウィンドウにおいて、対象のサブツリー単位でエクスポート・インポート、あるいは専用の `REORGANIZE SEGMENT` コマンドを実行する。

— メンテナンス用:断片化した契約明細セグメントの物理再編成
— ポインタチェインを維持したまま、フリースペースを再構築し物理的に連続配置する
REORGANIZE SEGMENT CONTRACT_SEGMENT
RESTORE PCTFREE 35;

—

5. まとめ:プロフェッショナルとして

階層型DBMSの設計は、単なる「データモデルの表現」ではない。「ハードウェアの物理特性(ストレージブロック、メモリキャッシュ)に、データのライフサイクルをいかに精密にフィットさせるか」という物理的エンジニアリングそのものだ。

デフォルト設定のままアプリケーションコードを書き始めるのは、航海図を持ずに荒海へ漕ぎ出すようなもの。
挿入・更新のワークロードを見極め、適切なフリースペースをデザインし、断片化の芽を設計段階から摘み取る。

このレベルのこだわりを持って初めて、「動くものを作った」ではなく「耐障害性と高パフォーマンスを担保したシステムをアーキテクトした」と言える。

次の設計書には、今日の話を必ず反映させてくれ。期待している。

コメント

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