【実務・中級編】 SHISAM (Simple HISAM) – 階層型DBMS

SHISAMの極意:なぜ現代のアーキテクトが今あえて「単純な階層構造」に立ち返るのか

こんにちは。チーフアーキテクトの私だ。

今日のコードレビュー、あるいはアーキテクチャ設計レビューで、また「とりあえず何でもRDB(あるいはNoSQL)のドキュメント指向で」という安易な設計を見かけて溜息をついたところではないか?

「マスター・ディテール構造のデータだからリレーショナルに」「いや、スキーマレスなJSONをそのまま突っ込めるからNoSQLだ」――ちょっと待て。本当にそのデータ構造、複雑な結合やアドホックなクエリが必要か? アクセスパスが完全に固定されており、ミリ秒単位の極限スループットと、物理I/Oの完全な制御が求められる領域において、私たちは先人たちが築き上げた最も純粋なアーキテクチャの一つを忘れていないか。

そう、SHISAM(Simple HISAM)だ。

今回は、IBMのIMS(Information Management System)などに代表される階層型DBMSの世界において、HISAM(Indexed Sequential Access Methodベースの階層構造)を極限までシンプルに削ぎ落としたSHISAMに焦点を当てる。
「レガシーな技術」と侮るなかれ。データの局所性(Locality)、ポインターチェーンの排除、そして物理シーケンシャルアクセスの極意を理解している者にとって、SHISAMは現代の超高速KVSや組込みストレージエンジンを設計する上でも極めて強力なインスピレーションの源泉なのだ。

実務で明日から使える堅牢な設計パターンと、パフォーマンスの罠をロジカルに伝授しよう。

—

1. SHISAMの本質:なぜ「ルートのみ」が最強の武器になるのか

まず大前提を整理する。通常のHISAM(Hierarchical Sequential Access Method)は、論理的な階層構造(ルート・セグメントの下に子、孫セグメントがぶら下がる形)を、VSAM(KSDS:Key-Sequenced Data Set)等のインデックス付き順編成データセット上に「物理的な連続領域」としてマッピングする手法だ。

しかし、SHISAMはその名の通り、これを極限まで単純化したものだ。
厳密には、SHISAMは「ルート・セグメントのみ」で構成されるデータベース、あるいはそれに準ずる非常にフラットな階層構造を対象とする。

[従来のHISAM: 複数レベルのセグメント]
ルート [Key: 001] —> 子セグメントA [Key: 101] —> 孫セグメント [Key: 901]
|
+—> 子セグメントB [Key: 102]

[SHISAM: ルートセグメントのみ(事実上のフラット構造)]
ルート [Key: 001] (データブロック内にすべての属性を保持、または単純なオーガナイゼーション)
ルート [Key: 002]
ルート [Key: 003]

「それってただのKVSや、単一テーブルのRDBと何が違うのか?」という声が聞こえてくる。
違う。OSのアクセスレイヤーとインデックス構造、そして物理バッファプールの占有戦略が完全にコントローラブルである点が決定的に違うのだ。

SHISAMでは、階層の深さが「1(ルートのみ)」であるため、親子間のポインターチェインを辿るオーバーヘッド(いわゆるデータベースエンジン内部のポインター・スィズリング)が一切存在しない。キーを指定すれば、VSAMのB-Treeインデックス(RBA/RRNの解決)を経て、一撃で目的のデータブロック(CI: Control Interval)へ到達できる。

—

2. スキーマ定義(DDL相当)と物理設計の勘所

階層型DBMSにおける定義は、データの論理構造と物理的なレコードレイアウトを直結させる必要がある。コードレビューで「この物理設計はヤバい」と見破るためのポイントを交え、仮想的な定義例を見てみよう。

  • =====================================================================
  • SHISAM データベース定義 (DBD) の概念モデル
  • 対象: 口座マスタ (Account Master)
  • アクセスパス: 口座番号 (Account-ID) による完全な一意索引アクセス
  • =====================================================================

DBD NAME=ACSTSHIS, ACCESS=SHISAM
DATASET DD1=ACSTDS01, DEVICE=3390, BLOCK=4096

  • ルートセグメントの定義 (SHISAMでは唯一のセグメント階層)

SEGM NAME=ACSTSEG, PARENT=0, BYTES=256,
PTR=NOTHING

  • フィールド定義 (キーと属性)

FIELD NAME=(ACCKEY,SEQ,U), BYTES=10, START=1, TYPE=C
FIELD NAME=ACCNAME, BYTES=60, START=11, TYPE=C
FIELD NAME=BALANCES, BYTES=16, START=71, TYPE=P
FIELD NAME=FILLER, BYTES=169, START=87, TYPE=X

END

チーフアーキテクトからの設計レビュー指摘:

1. `PTR=NOTHING` の美学:
子セグメントを持たないため、ポインター領域(4バイト〜8バイトの物理アドレス)をセグメント接頭辞(Prefix)に持たせる必要がない。純粋にデータ領域のみにバイト列を割り当てられるため、パディング効率が極限まで高まる。
2. CI(Control Interval / ブロック)サイズの選定:
上記の例では `BLOCK=4096`(4KB)としている。もし1レコードが256バイトなら、1つのCIに約16レコードが綺麗に収まる。VSAM KSDSのCIスプリット(分裂)を最小化するため、レコード長とCIサイズの倍率関係は徹底的に計算せよ。勘で決めるプログラマは即座に現場から外せ。

—

3. 実務における使用例:なぜ「今」SHISAM的アプローチが必要なのか?

「マスター・ディテール」のデータをあえてSHISAMのようにフラット化する、あるいはルートのみで表現するシステムとはどのようなものか。

典型例は、「極限のスループットが要求される金融の勘定系残高テーブル」や「IoTデバイスのメタデータ・ストア」だ。

複雑なJOINや、親子をまたぐアドホックなクエリ(例:「過去3ヶ月間に取引があった全顧客の子どものデータを集計しろ」のようなもの)が絶対に発生しないというビジネス要件がある場合、RDBの正規化は百害あって一利なしとなる。

アプリケーションコード(アクセスパターン)の模範例

C言語やCOBOL、あるいはモダンなバッチ基盤からSHISAMへアクセスする際のイディオムを疑似コードで示す。

/

  • SHISAMルートセグメントのランダム・アクセス (GU: Get Unique)
  • データベースエンジン内部でのポインター走査がゼロである点に注目せよ。

/
void fetch_account_balance(const char target_acc_key, AccountRecord out_rec) {
// パラメータリスト(PCB)の設定
IO_PCB pcb = get_account_pcb();

// 探索キーのセット
memcpy(pcb->search_arg, target_acc_key, 10);

// SHISAMに対するダイレクト・リード (GUコール)
// 戻り値: 0 = 成功, 状態コード (Status Code) による厳密な制御
int status = db_call(“GU”, pcb, out_rec);

if (status == DB_STAT_OK) {
// ヒット: 物理I/O最小限でデータ取得完了
process_record(out_rec);
} else if (status == DB_STAT_NOT_FOUND) {
// 該当キーなし
handle_not_found(target_acc_key);
} else {
// 致命的なI/Oエラーまたは構造異常
handle_fatal_error(status);
}
}

このコードの美しさは、「無駄なレイヤーが一切ない」ことだ。SQLのパース、オプティマイザによる実行計画の選択(テーブルスキャンかインデックススキャンかの迷い)、ロック競合の評価などというオーバーヘッドは、SHISAMの世界には存在しない。指定されたキーに基づき、VSAMのインデックスを引いて実データブロックを直撃する。それだけだ。

—

4. パフォーマンス上の罠と堅牢な運用パターン

しかし、アーキテクトとして警鐘を鳴らしておかなければならない。SHISAMはその「シンプルさ」ゆえに、設計を誤るとシステム全体を致命的な破滅に導く。

罠1:VSAM KSDSの「CIスプリット(Control Interval Split)」と「CAスプリット」

SHISAMはベースとしてKSDS(Key-Sequenced Data Set)を使用するため、ルートキーの順序に依存する。
もし、アプリケーションが完全にランダムなキー(例えばUUIDやハッシュ値)を生成してSHISAMにインサートし続けた場合どうなるか?

  • 結果:物理ブロック(CI)の空き容量が均等になくなり、ひっきりなしにCIスプリットが発生する。物理的なディスク上のページが断片化し、シーケンシャル・スキャン性能が完全に崩壊する。

【解決策:堅牢な設計パターン】

  • サロゲートキーの設計:キーには必ず「時系列でインクリメントされる値」または「プレフィックスに日付やパーティションIDを持つ値」を採用し、物理的なアペンド(追加)が局所化するように設計せよ。
  • 定期的な再編成(Reorganization):バッチウィンドウにおいて、定期的にアンロード/ロード(Reorg)を実施し、物理的な連続性を担保する運用フローをCI/CDパイプラインならぬ「運用パイプライン」に組み込め。

罠2:可変長セグメントの扱いの誤り

「ルートのみだから、ついでに可変長(Variable-length)にして大きなJSONでもぶち込んでおこう」――これを見た瞬間、そのエンジニアの頭を叩き割らなければならない。

SHISAMで可変長セグメントを多用すると、物理ブロック内のパッキング効率が狂い、オーバーフロー・チェーンや断片化の温床となる。

【解決策:固定長ファーストの原則】

  • データのコア部分は完全固定長(Fixed-length)で設計し、溢れた拡張データは別トライブ(あるいはオーバーフロー領域)に逃がすか、そもそもSHISAMの適用範囲外と見なせ。SHISAMの強みは「予測可能な物理レイアウト」にある。

—

5. チーフアーキテクトからの最終提言

現代のソフトウェアエンジニアは、「抽象化の階層」に毒されすぎていないか?
Frameworkの上にORMを重ね、その上にドキュメント指向の抽象化層を置き、遅くなったらスケールアウトすればいいと笑う。

だが、極限のトランザクション処理、ミリ秒を争う金融勘定系、あるいは限られたリソースで稼働するエッジコンピューティングの世界において、「ハードウェアの物理特性とメモリ/ディスクの局所性(Locality)」を直結させる技術は永遠に廃れることがない。

SHISAMは、階層型DBMSの歴史的遺物などではない。
「無駄を極限まで削ぎ落とし、キーと物理ストレージを最短距離で結ぶ」という、高パフォーマンス・アーキテクチャの原点なのだ。

次にデータベースの設計図を書くとき、自問してほしい。
「本当にその複雑なリレーションやスキーマレスな柔軟性は必要なのか? 俺たちは今、SHISAMの美しさを選ぶべきではないのか?」と。

健闘を祈る。厳格で妥協のない設計を期待している。

コメント

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