【実務・中級編】 データセットグループ (DSG) – 階層型DBMS

【伝説のアーキテクトが斬る】データセットグループ(DSG)極意:物理I/Oのボトルネックをねじ伏せる極限のスキーマ設計

おい、設計レビューの手を止めろ。そのスキーマ定義、本当に実運用に耐えられると思っているのか?

現代のクラウドネイティブな世界では、ストレージの抽象化が進み、物理ディスクの配置など意識しないエンジニアが増えた。だが、我々が対峙する階層型DBMS(IMS DBなどのヘビーデューティーな基幹系システム)の世界では、ハードウェアの物理特性を無視した設計は、本番稼働後の即死を意味する。

特に、巨大なデータベースを扱うプロジェクトにおいて、I/Oの競合はシステム全体のスループットを容赦なく殺す。ここで登場するのが、データセットグループ(DSG: Data Set Group)だ。

今回は、このDSGのメカニズムを骨の髄まで理解し、実務の現場でI/Oを極限まで最適化するための設計パターンを授けよう。レビューで後輩にドヤ顔で語れるレベルではなく、修羅場をくぐり抜けてきたアーキテクトとしての「生きた知見」を叩き込む。

—

1. そもそもDSGとは何の本質か?

階層型DBMSにおけるセグメント(リレーショナルデータベースでいう「行(レコード)」の集合に相当)は、ポインタによって親子関係がガチガチに結ばれている。標準状態では、これらは単一の物理データセット(OSファイル)上に直列に、かつ階層順に詰め込まれる。

ここで考えてみてほしい。
頻繁にアクセスされる「超高頻度のトランザクションセグメント」と、めったに見られない「巨大なアーカイブ用セグメント」が同一のデータセット、ひいては同一の物理LUN上に同居していたらどうなるか?

――I/Oヘッドの奪い合い(シーク待ちの嵐)が発生し、レイテンシが跳ね上がる。

データセットグループ(DSG)とは、1つのセグメントタイプ(あるいは複数のセグメントからなるサブツリー)を、論理的な構造を維持したまま、複数の物理データセットに分割・分散して格納する機能である。

[論理ビュー (DBHD)]
Root Segment (顧客マスタ)
├── Segment A (契約情報) ──> DSG 1へ配置 (高速SSD)
└── Segment B (監査ログ) ──> DSG 2へ配置 (大容量HDD)

これを使いこなすことで、アクセス特性の異なるセグメントを物理的に切り離し、I/Oの並列性を極限まで高めることができるのだ。

—

2. 実践:DDLによるDSGの定義と罠

論理的な階層定義(DBD: Database Definition)において、DSGをどのように定義するのか。具体的なコード例を見ていこう。

  • =====================================================================
  • 階層型DBMS DBD定義例:DSGによる物理分割
  • =====================================================================

DBD NAME=CUSTDB,ACCESS=HDAM,RMNAME=(DFSHDC40,1000,512)

  • ———————————————————————
  • 1. プライマリデータセット (ルートセグメントおよび高頻度セグメント)
  • ———————————————————————

DATASET DS1,DEV=3390,FILE=DD1,VOL=VOL001,
BLKSZ=4096,RRECS=(50000,10000)

  • ———————————————————————
  • 2. セカンダリデータセット (巨大・低頻度セグメント用 DSG)
  • ———————————————————————

DATASET DS2,DEV=3390,FILE=DD2,VOL=VOL002,
BLKSZ=32768,RRECS=(10000,5000)

  • ———————————————————————
  • 階層構造とDSGの紐付け (DSG= オプションによる物理割当)
  • ———————————————————————

SEGM NAME=ROOTSEG,BYTES=100 ルート (DS1に配置)
SEGM NAME=HIGHFREQ,BYTES=200,PARENT=ROOTSEG

SEGM NAME=ARCHIVSEG,BYTES=4000,PARENT=ROOTSEG,DSG=DS2

  • ↑【重要】ここでセグメントを物理データセット「DS2」へ逃がす

チーフアーキテクトからの鋭いツッコミ(罠の回避)

上記のコード、一見して問題なく動くように見えるだろう。だが、甘い。以下のポイントを外すと、本番で必ず痛い目を見る。

1. ブロックサイズ(BLKSZ)のチューニングミスマッチ

  • `DS1`(高頻度)はランダムアクセスが多いため、キャッシュ効率とオーバーヘッドのバランスを取ったサイズ(例: 4KB)。
  • `DS2`(アーカイブ)はシーケンシャルスキャンが主眼となるため、大きなブロックサイズ(例: 32KB以上)でスループットを稼ぐ。この使い分けができていない設計は即座に差し戻す。

2. ポインタのオーバーヘッド

  • DSGによってセグメントを別データセットに分割した場合、DBMSは内部的に「データセット間のポインタ(RBA: Relative Byte Address またはDSID付きポインタ)」を維持する必要がある。物理分割の代償として、わずかだがCPUコストと領域オーバヘッドが増加することを忘れるな。

—

3. 実務で使える堅牢な設計パターン

では、実際のシステム開発において、どのような基準でDSGを切るべきか。私が数々の修羅場をくぐり抜けて導き出した「3つの設計パターン」を授けよう。

パターンA:ホット/コールド分離パターン

  • 対象: 1つのレコードの中に「ステータスや直近の更新日時などの軽量で高頻度なデータ」と「数MBに及ぶBlobや巨大なXML/JSONドキュメント」が混在している場合。
  • 手法: ルート直下に軽量セグメントを置き、巨大なペイロードを持つセグメントだけを別DSG(低速かつ安価なストレージプール)へ切り出す。
  • 効果: メモリバッファプール(Buffer Pool)のヒット率が劇的に改善する。巨大データがバッファを汚染するのを防げるのだ。

パターンB:競合デッドロック回避パターン

  • 対象: 同一の親セグメントに対し、全く異なる業務アプリケーション(例:「受注処理バッチ」と「リアルタイム参照API」)から同時に子セグメントが追加される構造。
  • 手法: 業務ごとに子セグメントのタイプを分け、それぞれ異なるDSGに配置する。
  • 効果: 物理的なI/Oチャネルやエクステントの競合が軽減され、ロック競合に起因するスレッドのブロックを最小化できる。

—

4. パフォーマンス上の注意点:運用フェーズでの落とし穴

DSGを導入して「ハイ、設計完了」ではない。ここからが本当のエンジニアリングだ。運用フェーズにおいて、以下のメトリクスを常に監視し続けろ。

  • エクステント断片化(Extents Fragmentation)の監視

複数データセットに分割するということは、管理すべきファイル数が単純に倍増するということだ。各DSGが頻繁にエクステント(領域拡張)を起こしているようなら、初期割当値(`RRECS`パラメータ)のサイジングが根本的に間違っている。今すぐ再再編成(Reorganization)計画を立てろ。

  • I/Oバランスの偏り

OS側のパフォーマンスモニタ(iostat等)を使い、`DD1`とバインドされた物理ディスクと、`DD2`のディスクの間で、BUSY率や平均レスポンスタイムに著しい乖離がないか確認しろ。もし特定のDSGに負荷が集中しているなら、それはストレージLUNの設計ミスだ。

—

5. 結びにかえて

データセットグループ(DSG)は、階層型DBMSのポテンシャルを極限まで引き出すための「諸刃の剣」だ。

論理設計の美しさにこだわりすぎて物理特性を無視するのも素人の所業なら、場当たり的に物理分割を乱発して複雑怪奇なスキーマにするのも三流の仕事だ。

「論理の整合性を美しく保ちながら、物理のハードウェア制約をねじ伏せる」

これこそが、我々テクニカルリードに求められる仕事である。今回の知見を、君たちの次の設計レビューに役立ててほしい。妥協のないコードを期待する。

コメント

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