【入門編】ENVIRONMENT属性のBUFND/BUFNIパラメータによるVSAMパフォーマンスチューニング – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといったモダン、あるいはビジネス標準の言語をバリバリ書いてきた方にとって、IBMメインフレームの世界、そして「PL/I(ピーエルアイ)」という言語は、最初に少しだけ高くそびえ立つ壁のように感じられるかもしれません。

「なんだこの古い構文は……」「変数の命名規則はどうなっているんだ?」と不安になるかもしれませんが、大丈夫ですよ。怖がる必要はまったくありません。今日は、PL/Iのちょっとユニークな基本ルールに軽く触れつつ、基幹システムのバッチ処理などで避けて通れないVSAM(ヴィッサム)のパフォーマンスチューニングについて、実務の現場目線で優しく紐解いていきたいと思います。

—

1. ちょっと待って、PL/Iって「予約語」がないの?

JavaやCOBOLを経験した方なら、「`IF` や `READ`、`DATA` なんて名前の変数は作っちゃいけない(=予約語だから)」という常識がおありでしょう。

しかし、PL/Iの最もユニーク(で、最初はちょっとぎょっとする)な特徴の一つが、「PL/Iには厳密な意味での『予約語』が存在しない」という点です。

「えっ、じゃあ `IF` っていう変数名も作れちゃうの?」
その通りなんです。PL/Iのコンパイラは、文脈(コンテキスト)を見て「あ、ここで出てきた `IF` は条件分岐の `IF` だな」「こっちは変数の `IF` だな」と空気を読んで賢く判断してくれます。

例えば、こんなコードが書けてしまいます。

1
/ PL/Iの驚きの文脈依存性の例 /
DECLARE IF FIXED BIN(31); / 「IF」という名前の数値型変数を宣言 /
IF = 10; / 変数IFに10を代入 /

IF IF = 10 THEN / 最初のは条件分岐、2番めは変数 /
PUT SKIP LIST(‘変数IFの値は10です’);

「いやいや、そんな紛らわしいことしないよ!」と思われるかもしれませんが、この「予約語の呪縛がない」という仕様は、言語の柔軟性を高める一方で、過去の資産を引き継ぐマイグレーションの現場では「うっかりキーワードと同じ名前の変数を作ってしまい、コンパイラがどう解釈するかドキドキする」というスリリングなドラマを生み出します。でも、常識的な命名をしていれば何の問題もありませんので安心してくださいね。

—

2. 本題:VSAMのI/O遅延、その「大渋滞」をどう解消する?

さて、ここからが今回のメインテーマです。
メインフレームで大量のデータを高速に処理する際、切っても切り離せないのがVSAM(Virtual Storage Access Method)というデータセットです。KSDS(Key-Sequenced Data Set:索引編成データセット)などをバッチ処理でゴリゴリ読み込んでいるとき、こんなお悩みに直面したことはありませんか?

  • 「夜間バッチの処理時間が想定よりオーバーしている……」
  • 「サービストレースを見たら、CPU時間よりも圧倒的に I/O待ち時間(EXCP待ち) がボトルネックになっている!」

Javaでいうところの「データベースのコネクションプールが枯渇している」「N+1問題で毎回DBに丸め込まれている」ような状態が、メインフレームのファイルI/Oで起きているイメージです。

このI/Oの大渋滞を緩和する特効薬が、PL/Iのファイル定義(`ENVIRONMENT` 属性)で指定できる BUFND と BUFNI パラメータです。

—

3. 救世主パラメータ:BUFND と BUFNI とは?

VSAMのKSDSファイルを読み書きするとき、OS(正確にはJESやVSAM管理モジュール)は、DASD(外付けハードディスク)とメインメモリの間でデータをやり取りします。

ここで登場するのが2種類のバッファです。

1. BUFND (Buffer Number for Data)

  • データバッファの数です。実際にレコードの本体が入っているエリアをメモリ上にいくつ確保するかを指定します。
  • ここを増やすと、連続したデータ(順次処理)を読み込むときに、わざわざ毎回ディスクにアクセスせず、メモリ上から高速にデータを引っ張ってこれるようになります(先行読み込みの効果が高まります)。

2. BUFNI (Buffer Number for Index)

  • インデックスバッファの数です。「お目当てのレコードがどこにあるか」を示す索引情報をメモリ上にいくつ常駐させるかを指定します。
  • ランダムアクセス(キーを指定してピンポイントで1件ずつ読み込む処理など)が多い場合、このインデックスがディスク上にあると、レコードを探すたびにディスクがカチャカチャと何度も回り、凄まじいI/Oロスになります。ここを増やすと、上位のインデックスがメモリに常駐し、一発でデータにたどり着けるようになります。

—

4. 実践!PL/Iでの記述例とチューニングの作法

それでは、実際にPL/Iプログラムの中で、どのようにこれらを指定するのかを見てみましょう。JCL(ジョブ制御言語)側で指定する方法もありますが、プログラム側の `ENVIRONMENT` 属性でガチッと固定してしまうアプローチも現場ではよく使われます。

1
/ ========================================================== /
/ VSAM(KSDS)ファイルを高速化するためのPL/Iデータ宣言とI/O処理 /
/ ========================================================== /
FAST_BATCH_JOB: PROC OPTIONS(MAIN);

/ 1. ファイルの構造(レコード様式)を定義 /
DECLARE 1 CUSTOMER_REC,
5 CUST_ID CHAR(8), / 顧客ID (キー項目) /
5 CUST_NAME CHAR(30), / 顧客名 /
5 CUST_DATA CHAR(162); –- その他データ

/ 2. ファイルの論理的な結びつきと、チューニング属性の指定 /
/ ここが今回のキモ!ENVIRONMENT(BUFND(10) BUFNI(5)) です /
DECLARE CUSTFILE FILE RECORD
ENVIRONMENT(
KS / キー順データセット(KSDS)であることを明示 /
BUFND(10) / データバッファを10個に増やす(デフォルトより贅沢に) /
BUFNI(5) / インデックスバッファを5個に確保 /
);

/ 3. 処理用の変数定義 /
DECLARE EOF_FLG CHAR(1) INIT(‘0’);

/ ファイルのオープン(入力モード) /
OPEN FILE(CUSTFILE) INPUT;

/ 読み込みループ(順次アクセス:Sequential Read) /
DO WHILE (EOF_FLG = ‘0’);

READ FILE(CUSTFILE) INTO(CUSTOMER_REC);

/ ファイルの終端(エンド・オブ・ファイル)に達したときの処理 /
ON ENDFILE(CUSTFILE)
BEGIN;
EOF_FLG = ‘1’;
END;

IF EOF_FLG = ‘0’ THEN DO;
/ ここでビジネスロジック(データの加工や集計)を実行 /
/ 例: PUT SKIP LIST(CUST_ID); など /
END;
END;

/ ファイルのクローズ /
CLOSE FILE(CUSTFILE);

PUT SKIP LIST(‘バッチ処理が正常に完了しました。’);

END FAST_BATCH_JOB;

チューニングの現場でのリアルな判断基準

「じゃあ、BUFNDもBUFNIも、メモリが許す限り『999』とか大きくしちゃえば最強じゃん!」と思われるかもしれませんが、そこは限られたリソースを融通し合うメインフレームの世界。そう簡単にはいきません。

  • メモリ(仮想記憶領域)のトレードオフ:

バッファを増やすということは、その分だけタスクが占有する領域(Region)のメモリを消費します。バッチ多重度(同時に動かすジョブの数)が高いシステムで、すべてのジョブが勝手にバッファを巨大化させると、あっという間にシステム全体がストレージ不足(アベドumpなど)に陥ります。

  • 最適な値の見つけ方:
  • 大量の全件シーケンシャル処理(月次集計など): `BUFND` を多め(例: 10〜30以上)に割り当て、先行読み込みの恩恵を最大化します。
  • ランダムアクセス主体のオンラインリアルタイム更新や突合せ処理: `BUFNI` をインデックスの階層数(通常2〜4階層程度)に合わせてしっかり確保し、インデックスのI/Oを完全にゼロ(メモリヒット)に近づけます。

—

おわりに

いかがでしたでしょうか?
PL/Iという一見古めかしい言語も、背後にあるデータ構造(VSAM)やメモリ管理の仕組み(環境属性)と結びつけて考えてみると、モダンなアプリケーションのチューニング思想と根っこは同じであることが見えてきますよね。

「予約語がない」という自由度の高さに驚きつつも、堅牢な基幹システムを支えるこうした泥臭いチューニング技術を知っていくと、メインフレームプログラミングもなかなか奥が深くて面白いものです。

レガシーシステムの改修や移行で壁にぶ1つ当たったときは、ぜひ「バッファの大きさとI/Oのバランス」を思い出してみてください。あなたの書いたコードが、夜間バッチの時間を劇的に短縮する救世主になる日がきっと来ますよ!

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