【第1回】データセットグループ(DSG)の極限最適化:物理の限界を超えろ
おい、設計レビューの手を止めてくれ。今お前が書いたそのスキーマ定義、本当にミリ秒単位のレイテンシー要求に耐えられると思っているのか?
現代の開発現場では「RDBかNoSQLか」「クラウドネイティブか」といった高レイヤーの議論ばかりがもてはやされがちだ。だが、金融、航空、社会インフラといった、1秒間に数十万件のトランザクションをさばき、絶対に止まることが許されない領域の裏側では、今なお階層型DBMS(IMS DBなど)がその超絶的なスループットで世界を支えている。
そして、その極限性能を引き出すための最大のキーストーントリガーが、今回解説するデータセットグループ(DSG: Data Set Group)の設計だ。
リレーショナルデータベースの「テーブルスペースの分割」などという生ぬるい概念と一緒にしてもらっては困る。DSGの本質は、論理的な階層構造を持つ単一のデータベースを、物理的な複数のファイル(データセット)へどのように分散配置し、I/Oのボトルネックを物理レベルで粉砕するかにある。
今日のレビューでは、このDSGのメカニズムを骨の髄まで叩き込む。プロのエンジニアとしての誇りにかけて、物理I/Oの悪夢を避けるための設計パターンをマスターしてくれ。
—
1. そもそもDSG(データセットグループ)とは何物か
階層型DBMSにおけるデータ構造は、親セグメントと子セグメントがポインタで結ばれた「ツリー構造」を基本とする。標準状態では、このツリー全体の全セグメントが、単一の物理データセット(OSファイル)上に直列的に、あるいはクラスタリングされて格納される。
だが、考えてみてほしい。
一つのツリーの中に、以下のような特性が混在していたらどうなるか?
- 頻繁に参照・更新される「口座基本情報セグメント」(アクセス頻度:極めて高)
- めったにアクセスされないが巨大な「過去10年分の取引明細セグメント」(アクセス頻度:極めて低)
これらを同一の物理ファイルに詰め込んでおけば、OSのバッファプールは常に阿鼻叫喚の嵐となる。明細データを読み込むために基本情報のキャッシュが追い出され、ディスクシークの嵐によってI/O待機時間が跳ね上がる。
ここで登場するのが DSG(Data Set Group) だ。
DSGを用いることで、一つの論理データベース(DBD: Database Definition)を最大で10個(標準的なIMSの仕様)の物理データセットに分割し、ツリーのセグメントを意図した物理ファイルへ振り分けることができる。
—
2. 伝統と実践:DBD言語によるDSGの定義コード
百聞は一見に如かず。実際にDBD(Data Base Description)マクロを用いたスキーマ定義のコードを見てみよう。コードレビューのつもりで細部まで目を凝らせ。
———————————————————————-
- データベース定義 (DBD) – DSG活用モデル
———————————————————————-
PRINT NOGEN
DBD NAME=ACCLOGDB,ACCESS=(HDAM,RWRT),RMNAME=(DFSHDC40,50,500)
- ———————————————————————
- 物理データセットの定義 (DSG 1〜3)
- ———————————————————————
DSG1 DATASET DD1=ACCMAST,DEVICE=3390,BLOCK=4096 プライマリDSG
DSG2 DATASET DD1=ACCTRNS,DEVICE=3390,BLOCK=32768 セカンダリDSG (大容量)
DSG3 DATASET DD1=ACCARCH,DEVICE=3390,BLOCK=32768 セカンダリDSG (アーカイブ)
- ———————————————————————
- セグメント構造とDSGの紐付け
- ———————————————————————
SEGM NAME=ROOTSEG,PARENT=0,PTR=T,BYTES=(128)
LCHILD NAME=(XREFNAME,XREFDBD),POINTER=SNGL
FIELD NAME=(ACCNO,SEQ,U),BYTES=10,START=1
- ※ 親セグメントはプライマリDSG(DSG1)に自動配置される
SEGM NAME=SUBSEG01,PARENT=ROOTSEG,PTR=TWIN,BYTES=(256),
DSG=DSG1
- ↑ 高頻度アクセスのサブセグメントは実効性の高いDSG1に置く
SEGM NAME=TRXSEG02,PARENT=ROOTSEG,PTR=TWIN,BYTES=(1024),
DSG=DSG2
- ↑ トランザクション明細は巨大ブロックのDSG2に分離!
SEGM NAME=ARCSEG03,PARENT=ROOTSEG,PTR=TWIN,BYTES=(4096),
DSG=DSG3
- ↑ 過去アーカイブは別ボリューム(DSG3)へ完全隔離
END
コードの急所解説
1. `DSG` パラメータによる物理分離:
各 `SEGM` マクロの `DSG=` オペランドに注目してほしい。論理的な親子関係はそのまま維持しつつ、物理的な格納先ファイル(`ACCMAST`, `ACCTRNS`, `ACCARCH`)を完全に切り離している。
2. ブロックサイズの最適化(BLOCK=):
- `DSG1` はランダムアクセスとマスター検索が多いため、キャッシュ効率とオーバーヘッドを考慮して `4096` バイト(4KB)と小さめに設定。
- `DSG2` や `DSG3` はシーケンシャルなスキャンが多いため、OS/物理デバイスの転送効率を最大限に引き出すために `32768` バイト(32KB)の大きなブロックサイズを割り当てている。この非対称なチューニングこそがチーフアーキテクトの技だ。
—
3. 堅牢な設計パターン:アンチパターンを駆逐せよ
現場でありがちな失敗作を挙げておこう。お前の設計がこれに該当していないか胸に手を当てて考えてほしい。
❌ アンチパターン:「何でもかんでも単一DSG(デフォルト)」
「セグメント数が少ないから」「管理が面倒だから」という理由で全てのセグメントを1つの物理ファイルに押し込める設計。
結果:ホットスポット(特定レコード群)へのアクセスが集中した際、ファイルロックやバッファ競合が発生し、CPU使用率が100%に張り付いたままスループットが激減する。
⭕ 模範解答:アクセス特性マトリクスに基づく「垂直・水平分離」
設計時には、必ず以下のマトリクスを作成し、DSGの割り振りをロジカルに証明できなければならない。
| セグメント名 | アクセス頻度 | レコード長 | 推奨DSG | 物理デバイス選定の理由 |
| :— | :— | :— | :— | :— |
| ROOTSEG (基本) | 极高 (1000回/秒) | 小 (128B) | DSG1 | 超高速SSD / 高速キャッシュ常駐エリア |
| TRXSEG02 (明細) | 中 (50回/秒) | 大 (1024B)| DSG2 | 標準ストレージ / スループット重視領域 |
| ARCSEG03 (履歴) | 极低 (月数回) | 特大 (4KB)| DSG3 | 大容量・低コストストレージ(ニアライン) |
このように、「アクセスの熱量」と「データの容量」の直交軸で物理ファイルを切り離すこと。これが堅牢なDSG設計の鉄則だ。
—
4. パフォーマンス上の注意点(実務の罠)
DSGを導入すれば万事解決、というわけではない。アーキテクトとして、以下のトレードオフとリスクを常にコントロール下に置く必要がある。
1. ポインタチェインのコスト(I/Oの横断)
DSGを分けるということは、論理的な親子・きょうだい関係のセグメント間を移動する際に、異なる物理ファイル間(あるいは同一ファイル内の遠く離れた領域)をポインタがまたぐことを意味する。無駄にDSGを細分化しすぎると、ポインタ追跡のためのシークが発生し、かえってパフォーマンスが劣化する。
2. ストレージI/Oパスの独立性
ファイルを分けるだけでは不十分だ。OSやストレージのレイヤで、`DSG1`(マスター)と `DSG2`(明細)が全く同じ物理SSD(LUN)上に配置されていたら意味がない。ストレージ管理チームと連携し、物理的なコントローラーやチャネルパスレベルでI/Oが競合しないようにチャネルを分散させること。ここまでやって初めて「アーキテクチャ設計」と呼べる。
3. リカバリ・バックアップの複雑化
DSGを分けると、データベース全体のバックアップ・イメージだけでなく、DSG単位での部分的なリカバリや、ジャーナル(ログ)の整合性管理が複雑化する。運用フェーズのコストも計算に入れて分割粒度を決めろ。
—
チーフアーキテクトからの最後のアドバイス
階層型DBMSのDSG定義は、単なるテキストの編集作業ではない。それは、「ハードウェアの物理特性」と「ビジネスのデータアクセスパターン」を結婚させる極めて高度なエンジニアリングだ。
コードを書く前に、データがどう流れ、ディスクがどううめき、キャッシュがどう呼吸しているのかを脳内でビジュアライズしろ。
妥協したスキーマは必ずシステムの本番障害という牙をむいておそいかかってくる。
次のレビューでは、もっとシビアな数字を持ってこい。期待しているぞ。
コメント