IBM i ODBC/JDBCパフォーマンスチューニングに役立つAPI QWTRAPJS

## IBM i (Db2 for i)のODBC接続サポート

IBM純正として提供されているODBCドライバーには以下のようなものがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/463780a2-5a2d-ab98-a3e7-e785ee5d23f8.png)

歴史的に見れば色々な製品にバンドルしてODBCドライバーが提供されてきましたが、現在一番メジャーなのはACS (IBM i Access Client Solutions）に付属のODBCドライバーでしょう。ACSでWindows, Linux, MacOS用のODBCドライバーが提供されています。
本題ではないので省略しますが、IBM i の箱の中（IBM i OS上）にあるPASE、とはIBM i OSのUNIX（AIX）互換ランタイム環境です。PASEはほぼ完全にUNIX環境でPythonなどからODBC接続ができます。

### ACSのダウンロードURL
ACSは以下のサイトから入手可能です。※要IBM ID作成（無料）
**http://ibm.biz/IBMi_ACS**

### ACSって何？を聞きたい方は、、、
ACSの解説記事はこちらです。
[【できるIBM i 7.4解剖】第6回 「あらためてACSとは」](https://www.i-cafe.info/column/serials/dekiruibmi_no6)

## Db2 for iのODBC/JDBCアクセスの仕組み

Db2 for iへのODBC/JDBCでパフォーマンスがでない場合の原因は様々ですが、よくあるのは、
・DBテーブルに必要な最適なインデックスが作成されていない
・アプリケーションコードの問題（不適切なSQL構文、ハードオープン・クローズが多発
が多いように思います。
また、ODBCドライバーの設定でもブロックサイズ設定などがあるかと思います。

### IBM i ODBCドライバーの設定方法など
こちらの記事をどうぞ。
[【できるIBM i 7.4解剖】第8回 「Db2 for i のODBCサポート」](https://www.i-cafe.info/column/serials/dekiruibmi_no8)

上記以外にもODBCのパフォーマンスに影響を与える、IBM i上のODBC/JDBCサーバージョブQZDASOINITの動作について説明します。なお、QZDASOINITはODBC/JDBC共通のサーバージョブ（デーモン）なので以下はJavaからのJDBCアクセスのパフォーマンスチューニングにも参照できます。

図2. 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/e106b341-5c8b-c6bf-3dc0-4d80c7d08426.png)

・QZDASOINITサーバージョブはOSデフォルトではQUSRWRKサブシステム起動時に2つのQZDASOINITジョブ（事前開始ジョブ Pre-Start Job）が起動します。
・QZDASOINITはDB接続のコネクションプールとして機能し、通常複数個のジョブが常駐しクライアントからのリクエストに応答します。
・デフォルトでは2つジョブが起動していますので同時に3つ以上のODBC/JDBCリクエストが発生するとQZDASOINITのジョブが追加起動します。

## ODBC/JDBCの接続ジョブであるQZDASOINITの特性
・QZDASOINITはじめサーバージョブの開始はCPUコストが高い処理です。QZDASOINITを追加で起動する操作はシステム負荷が高く結果レスポンスタイム等パフォーマンスに影響を及ぼす事があります。
・QZDASOINITはシステムIPL時(サブシステム開始時)に指定されたジョブ数（デフォルトは2つ）を起動しておき、実際のユーザーからのアクセス時パフォーマンスが低下しないように考慮されています。
・一方でQZDASOINITジョブの実行中は同期I/O処理が定常的に発生してしまいます。同期I/O処理はシステム負荷、特にI/O負荷（IBM iではHDD等のアームビジー率）に影響を与えるため、無用に多く起動することは推奨されません。
・IPL時に起動されるQZDASOINITのジョブ数（デフォルトは2つ）と実際に利用するODBCクライアント数の差が大きいと、ユーザーリクエストが発生した時点で追加のQZDASOINITジョブ起動が多数発生しパフォーマンス劣化を引き起こす可能性があります。

**以上から一般的な考え方としては、ピーク時のODBC/JDBCクライアントから同時実行数や、最も一般的な時間帯のODBCクライアント数と同数程度QZDASOINITジョブを起動しておくことが最良なシステムパフォーマンスを発揮する可能性が高いと考えられます。**

## 従来のQZDASOINITジョブ数の確認・調整方法
詳しくは下記のリンクを参照ください。簡単にいうと、DSPACTPJコマンドでQZDASOINITジョブ数の過去の最大値、現在の値を調べる、という事になります。
[【できるIBM i 7.4解剖】第9回 「Db2 for iのODBC/JDBCサーバージョブ QZDASOINITのパフォーマンス調整」](https://www.i-cafe.info/column/serials/dekiruibmi_no9)

## API QWTRAPJSによるQZDASOINITジョブ数の監視
ここからが本記事の本題です。
**API QWTRAPJS (Retrieve Active Prestart Jobs Status)** はIBM i 7.4で初めて実装されたAPIです。

QWTRAPJSの機能はその名の通りですが、QZDASOINITほか事前開始ジョブの起動数をAPI取得しプログラムに返す事です。今回のODBC/JDBC接続ジョブ以外にも近年のIBM i では様々な事前開始ジョブが利用されており、その起動数の確認や調整はパフォーマンス管理にとても有用です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/d7b75a9b-dfd1-72bb-912c-0c4d5fc7faca.png)

QWTRAPJSコマンドを監視プログラム等に組込んで定期的に実行させ、取得したピークの起動数＝ODBC/JDBCの同時リクエスト処理数のピーク数 を基準に（たとえばピークの数が20なら20前後の値に）QZDASOINITの開始ジョブ数を調整する事が考えられます。
CHGPJEコマンドの使い方は、[先のリンク記事](https://www.i-cafe.info/column/serials/dekiruibmi_no9)にあります。

### API QWTRAPJS のパラメーター
一覧は下記のとおりです。
ODBC/JDBCの場合、サブシステム名にQUSRWRK, 事前開始ジョブ名にQZDASOINITを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/51b1abd0-6256-ea83-249f-221fdc19131e.png)

### API QWTRAPJS マニュアルページ
パラメーターの説明、エラーメッセージの説明など
[IBM Docs : Retrieve Active Prestart Jobs Status (QWTRAPJS) API](https://www.ibm.com/docs/en/i/7.5?topic=ssw_ibm_i_75/apis/qwtrapjs.html#HDRRAPJSDE)

### ※ POWER10サーバーの標準ストレージがNVMeに変化した影響の考察
NVMeは従来のSSD, HDDと比べて処理速度が文字通りケタ違いに速くなっています。このことはおそらくQZDASOINITジョブの同期I/O処理に負荷にもいい影響を与えているのではないでしょうか。
まだ実際のパフォーマンスデータ等で確認できてはいませんが、SSD, HDDに比べて同期I/O多発の影響を低減できているかもしれません。
つまり、NVMe搭載POWER10サーバー（以降）ではQZDASOINIT数を従来より多く起動させておいてもパフォーマンス劣化が抑制される可能性があると思います。
これはデータを取得していずれ比較してみたいと考えています。