OpenFrame VSAMのパフォーマンス最適化

本付録では、OpenFrame VSAMのパフォーマンスの最適化方法について説明します。

1. 概要

OpenFrame 7 VSAM(TSAM)は、JCLユーティリティのIDCAMSまたはコマンド・ライン・ツールのidcamsを使用して定義することができます。

OpenFrame 7 VSAMはRDBテーブルとして定義されます。テーブルの構造は、ds.TSAM_RDB.COPYBOOK_PATHとして設定されたディレクトリで生成するデータセットと同じ名前のコピーブック・ファイルを参照して定義されます。そのコピーブックは、テーブル定義およびOpenFrameエンジンの動作でのみ使用されるため、移行スキーマやユーザー・プログラムのFD定義と同じである必要はありません。

以下は、フィールド・タイプに応じて定義される列タイプです。

フィールド・タイプ 列タイプ 備考

文字(X、N)

VARCHAR

Zoned/Packed decimal,

binary(COMP,COMP-4,COMP-5)

NUMBER

Float(COMP-1)

BINARY_FLOAT

Double(COMP-2)

BINARY_DOUBLE

EBCDIC(EBC)

NVARCHAR2

X、Aタイプでのみ使用できます。EBCDICソートを使用するには、EBCタイプを使用する必要があります。

例) PIC X(10) EBC.

OpenFrame 7 VSAMは、ユーザーの必要に応じてデータが適切に列化されてテーブルに格納されるため、RDBの利点を最大限に活用し、他の現代的なシステムおよびアプリケーションと簡単に連携できるというメリットがあります。

ただし、COBOLプログラムの入出力では、列化されたデータを読み取るときはバイト配列でシリアル化し、書き込むときは逆シリアル化するプロセスが必要となるため、追加コストが発生します。したがって、実行時間が重要なバッチ業務の場合は、パフォーマンスの最適化が必要になる場合があります。

ds.TSAM_RDB.PRINT_DEBUG_MSG_ONの設定をYESにすると、OpenFrame 7 VSAMは、プログラム命令に従ってエンジンから要求されたSQLや実行時間を出力します。

以下のログの例です。

 [START]
  * SQL
   SELECT /*+ INDEX_ASC (BASE "PROD_VSAM_KEY") */ SM_KEY, STYLE_NUMBER, YEAR, SIZE, SIZE_SCALE_PCT, EACH_PRICE_1, EACH_PRICE_2, EACH_PRICE_3, EACH_PRICE_4 FROM "PROD_VSAM" BASE  WHERE ("SM_KEY", "STYLE_NUMBER", "YEAR", "SIZE") >= (:SM_KEY, :STYLE_NUMBER, :YEAR, :SIZE) AND ROWNUM = 1  ORDER BY "SM_KEY", "STYLE_NUMBER", "YEAR", "SIZE" ASC
  * KEY
   SM_KEY(50), STYLE_NUMBER(000100009), YEAR(22), SIZE()
  * Current Time   : 2023-03-06 11:26:03
  * Execution Time : 0.0020s

 [OPEN]
  * SQL
   SELECT /*+ INDEX_ASC (BASE "PROD_VSAM_KEY") */ SM_KEY, STYLE_NUMBER, YEAR, SIZE, SIZE_SCALE_PCT, EACH_PRICE_1, EACH_PRICE_2, EACH_PRICE_3, EACH_PRICE_4 FROM "PROD_VSAM" BASE  WHERE ("SM_KEY", "STYLE_NUMBER", "YEAR", "SIZE") >= (:SM_KEY, :STYLE_NUMBER, :YEAR, :SIZE)   ORDER BY "SM_KEY", "STYLE_NUMBER", "YEAR", "SIZE" ASC
  * KEY
   SM_KEY(50), STYLE_NUMBER(000100009), YEAR(22), SIZE(1X         )
  * Current Time   : 2023-03-06 11:26:03
  * Execution Time : 0.0441s

上記の例で、実行時間が長いSQLを対象に実行計画などを確認してチューニングポイントを見つけます。

2. その他のパフォーマンス最適化方法

以下は、その他のパフォーマンス最適化方法です。

  • コピーブック・フィールドの数を減す

    列の数が多くなるほどSQLの処理性能が低下し、OpenFrameエンジンにも負荷がかかります。したがって、フィールドを結合して列の数を減らすことで、入出力の速度を向上させることができます。

  • コピーブック・フィールドをX型として作成

    ゾーン10進数、パック10進数、整数型のフィールドの場合、COBOL規約に適合するデータ形式とRDBに格納される数値形式が異なるため、入出力時にデータ変換が必要となります。したがって、このようなフィールドが多くなると負荷が大きくなります。

    一方、X型のフィールドはデータ変換なしで、VARCHAR列にそのまま格納されるため、比較的高速な入出力が可能です。

    上記の2つのケースを組み合わせて、コピーブックをインデックスキーとして使用するX型のフィールド1つと、データの残りの部分に対するX型のフィールド1つに単純化すれば、COBOLプログラムの入出力パフォーマンスを向上させることができます。ただし、その分だけSQLを使用したデータ操作が難しくなるデメリットもあります。

  • PAGESIZEオプションの使用

    一部のユーザー・プログラムでは、レコードの総数に比べREADコマンドで一度に読み取られるレコード数が少ないため、READコマンドが繰り返される場合があります。 OpenFrameエンジンは、READコマンドが繰り返されることを正常と判断し、READコマンド時にそのキーの後のレコードをすべて取得するクエリを実行しますが、このクエリはレコード数が多いほど実行速度が遅くなるため、動作効率が低下します。

    JCLのDCBに以下の例のようにPAGESIZE=nオプションを与えると、一度に読み取るレコード数を指定できるため、ジョブに応じてこのオプションを適切に指定して実行時間を短縮することが可能です。

    //JOB0    EXEC PGM=READTEST
    //DDONE   DD DSN=TEST.VSAM,DISP=OLD,
    //         DCB=(PAGESIZE=100)
    //SYSOUT  DD SYSOUT=*
    //SYSPRINT DD SYSOUT=*