COBOLバッチ処理の並列ジョブ実行とは?メリット・デメリットを徹底解説
生徒
「大量のデータを処理するバッチ処理を早く終わらせる方法ってありますか?」
先生
「それなら並列ジョブ実行という方法があります。複数の処理を同時に動かす仕組みのことですよ。」
生徒
「同時に動かすとどんな良いことがあるんですか?逆に注意点も知りたいです!」
先生
「並列実行は時短になりますが、管理が少し複雑になります。基本から詳しく解説しますね!」
1. バッチ処理とジョブの基本を知ろう
コンピュータの世界にはバッチ処理という言葉があります。これは、人間が操作しなくても、あらかじめ決めておいた手順に従って大量のデータをまとめて処理することを指します。例えば、銀行の利息計算や、通販サイトの1日分の売り上げ集計などがこれにあたります。
そして、このバッチ処理の中で実行されるひとまとまりの作業単位をジョブと呼びます。通常、プログラムは1つずつ順番に動かしますが、これを順次実行といいます。しかし、データがあまりにも多いと、順番に待っていては時間がかかりすぎてしまいます。そこで登場するのが、今回のテーマである並列実行です。
COBOLは古い言語だと思われがちですが、実はこのような大量データを処理する能力が非常に高く、今でも多くの企業の基幹システムで現役で動いています。まずは、もっともシンプルなCOBOLプログラムの形を見てみましょう。これは画面に文字を出すだけのジョブです。
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-JOB.
PROCEDURE DIVISION.
DISPLAY "ジョブを開始します。".
STOP RUN.
2. 並列ジョブ実行の仕組みとは
並列ジョブ実行とは、複数のジョブを同じタイミングで同時に動かす仕組みのことです。身近な例で例えると、大掃除をイメージしてください。1人で「窓拭き」をして、それが終わってから「床掃除」をして、次に「お風呂掃除」をするのが順次実行です。これだと時間がかかりますよね。
一方で、3人で手分けして、1人が窓、1人が床、1人がお風呂を同時に掃除するのが並列実行です。コンピュータの中でも、これと同じように計算を行う頭脳(CPU)を複数使って、別々のプログラムを同時に動かすことができるのです。
COBOLのバッチ運用管理においては、ジョブネットと呼ばれる実行手順書のようなものを作成し、どの処理を同時に動かしてよいかを設定します。これにより、コンピュータの持っている力を最大限に引き出すことが可能になります。ただし、何でもかんでも同時にすれば良いというわけではありません。それについては後ほど詳しく説明します。
3. 並列ジョブ実行の大きなメリット
最大のメリットは、何といっても処理時間の短縮です。これを専門用語でスループットの向上と言います。夜中の限られた時間内に終わらせなければならないバッチ処理において、時間は命です。並列化することで、3時間かかっていた処理を1時間に短縮できる可能性があります。
また、コンピュータ資源の有効活用もメリットです。最近のサーバは非常に高性能で、1つのプログラムを動かすだけでは力が余ってしまいます。並列に動かすことで、眠っている性能をフルに活用できるようになります。これにより、会社全体のシステム効率が上がり、コストパフォーマンスも良くなります。
さらに、処理の独立性が高まる点も挙げられます。例えば、東京支店の集計と大阪支店の集計を別々のジョブとして並列に動かせば、もし大阪支店のデータに不備があってエラーが起きても、東京支店の処理は止まらずに完了させることができます。このように、リスクを分散できるのも大きな強みです。
4. 並列ジョブ実行のデメリットと注意点
良いことばかりに見える並列実行ですが、デメリットもあります。一番の課題はリソースの競合です。リソースとは、メモリやディスク、データベースなどのコンピュータ資源のことです。複数のプログラムがいっせいに同じデータに書き込みをしようとすると、順番待ちが発生したり、データがおかしくなったりすることがあります。これを排他制御(はいたせいぎょ)の問題と言います。
また、運用の複雑化も避けられません。順次実行であれば、エラーが起きた場所が分かりやすいですが、並列実行だと「どのジョブが原因で全体が遅れているのか」を見つけるのが難しくなります。ジョブ同士の関係性が複雑になるため、設計段階でしっかりとした計画を立てる必要があります。
他にも、ハードウェアへの負荷が急激に高まることがあります。同時にたくさんの処理が動くと、一時的にメモリが足りなくなったり、ディスクの読み書きが追いつかなくなったりして、逆に全体の速度が落ちてしまうこともあるのです。これを防ぐためには、どの程度の並列数が適切かを見極める性能テストが欠かせません。
5. 排他制御の重要性を理解する
先ほど少し触れた排他制御について、もう少し詳しく解説します。例えば、ある商品の在庫が残り1個だとします。2つの並列ジョブが同時に「在庫を確認して、1個減らす」という処理をしようとしたとき、適切な制御がないと、両方のジョブが「在庫はある」と判断してしまい、結果として在庫がマイナスになってしまうかもしれません。
これを防ぐために、1つのジョブがデータを使っている間は、他のジョブが触れないように「鍵」をかける仕組みが排他制御です。COBOLプログラムを書く際や、データベースを設計する際には、この鍵のかけ方を慎重に考える必要があります。
次に、ファイルからデータを読み込んで集計する、並列化を意識した基本的なCOBOLプログラムの構造を見てみましょう。特定の支店コードのデータだけを処理するイメージです。
IDENTIFICATION DIVISION.
PROGRAM-ID. BRANCH-SUM.
DATA DIVISION.
FILE SECTION.
FD SALES-FILE.
01 SALES-REC.
05 BRANCH-CODE PIC X(04).
05 AMOUNT PIC 9(08).
WORKING-STORAGE SECTION.
01 TOTAL-AMOUNT PIC 9(12) VALUE 0.
01 TARGET-BRANCH PIC X(04) VALUE "1001".
PROCEDURE DIVISION.
DISPLAY "支店コード " TARGET-BRANCH " の集計を開始します。".
* ここで本来はファイルを読み込み集計するループが入ります
ADD 50000 TO TOTAL-AMOUNT.
DISPLAY "合計金額: " TOTAL-AMOUNT.
STOP RUN.
6. データの分割(パーティショニング)のコツ
並列実行を成功させる鍵は、データをいかに綺麗に分けるかです。これをパーティショニングと呼びます。例えば、顧客名簿を処理する場合、五十音順で「あ~さ行」を担当するジョブと「た~わ行」を担当するジョブに分けるようなイメージです。
データが均等に分かれていないと、特定のジョブだけがいつまでも終わらず、結局全体の終了時間が遅くなってしまいます。これをボトルネックと言います。並列化の設計では、各ジョブの仕事量が同じくらいになるように工夫することが大切です。
また、分けたデータを最後につなぎ合わせる処理も必要になります。バラバラに計算した合計値を、最後に合算するジョブを別途用意するなどの手順を組みます。このような「分けて計算して、最後にまとめる」という考え方は、現代のビッグデータ処理でも使われている非常に重要な概念です。
7. バッチ運用管理ツールでの設定
実際の現場では、プログラムを直接手で動かすのではなく、運用管理ツール(ジョブスケジューラ)を使って管理します。有名なものだと、JP1やSystemwalkerといったソフトがあります。これらのツールを使うと、マウス操作で「ジョブAとジョブBは同時に動かす」「ジョブCは、AとBが両方終わってから動かす」といった複雑なスケジュールを組むことができます。
管理者は、このツールの画面を見て、今どのジョブが動いているのか、エラーが出ていないかを監視します。並列実行を設定する場合、依存関係の定義を間違えると、データが揃っていないのに次の処理が始まってしまうなどのミスが起きるため、細心の注意が必要です。
設定の一環として、もしエラーが起きたときに自動で再実行(リトライ)させる設定や、担当者にメールで通知する設定なども行います。これにより、深夜のバッチ処理でも安定して運用できるようになっています。初心者の方は、まずはプログラムそのものよりも、この「実行の順番待ち」という概念を覚えるのが近道です。
8. 実践的なCOBOLの並列処理対応プログラム
並列ジョブとして動かす場合、プログラム側で自分がどの範囲を担当すべきかを受け取れるようにしておくのが一般的です。例えば、外部から「今日は支店Aを担当してね」という指示を受け取るような仕組みです。COBOLでは引数(パラメータ)を使ってこれを実現します。
IDENTIFICATION DIVISION.
PROGRAM-ID. PARAM-JOB.
DATA DIVISION.
LINKAGE SECTION.
01 PARAM-AREA.
05 IN-BRANCH-ID PIC X(04).
PROCEDURE DIVISION USING PARAM-AREA.
IF IN-BRANCH-ID = "2001"
DISPLAY "大阪支店のデータを処理します"
ELSE
DISPLAY "その他の支店を処理します"
END-IF.
STOP RUN.
このようにプログラムを汎用的に作っておけば、同じプログラムをコピーすることなく、パラメータを変えるだけで複数の並列ジョブとして使い回すことができます。これは保守性の向上にもつながるプログラミングのテクニックです。
9. 並列実行と順次実行の使い分け
全てのバッチ処理を並列化すればいいわけではありません。順次実行が適している場合もあります。例えば、データの更新履歴を順番に記録しなければならない処理や、前の処理の結果を次の処理が必ず必要とするような、ステップが密接に関係している場合です。
逆に、データの数が多いだけで、それぞれのデータが独立している場合は並列実行の出番です。例えば、全社員に給与明細メールを送る処理などは、一人一人の処理は独立しているので、100人ずつ一斉に送るように並列化すると劇的に早くなります。
判断基準としては、「データの前後関係があるか」「リソースを独占する必要があるか」を考えます。複雑なロジックであればあるほど、まずは安全に順次実行で作り、速度が問題になったときに並列化を検討するというのが、トラブルを少なくする賢い開発の進め方です。
10. エラー発生時のリカバリ方法
並列実行中にエラーが起きたときの対応は、初心者にとって少し難しいかもしれません。複数のジョブが動いているため、どの状態まで処理が進んだのかを正確に把握する必要があります。これをリカバリ(復旧)作業と言います。
並列ジョブの場合、失敗したジョブだけを再実行すればよいのか、それとも関連するジョブも含めて最初からやり直すべきなのかを判断しなければなりません。そのためには、プログラムの中で「どこまで終わったか」をログという記録に残しておくことが不可欠です。以下に、ログを出力する簡単なプログラムの例を示します。
IDENTIFICATION DIVISION.
PROGRAM-ID. LOG-CHECK.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 CURRENT-STATUS PIC X(20).
PROCEDURE DIVISION.
MOVE "処理開始" TO CURRENT-STATUS.
DISPLAY "STATUS: " CURRENT-STATUS.
* 何らかの計算処理
MOVE "データ更新完了" TO CURRENT-STATUS.
DISPLAY "STATUS: " CURRENT-STATUS.
STOP RUN.
こうした細かい記録があれば、万が一夜中にジョブが止まっても、管理者はログを見て迅速に対応できます。並列ジョブ実行は、スピードという大きなメリットを得る代わりに、こうした準備や気配りが求められる高度な運用技術なのです。