Db２の稼働状況をレポートするdb2mon

## 1. db2monとは
db2monとは、Db2の稼働状況をレポートするツールです。製品マニュアルでも紹介しています。[(link)](https://www.ibm.com/docs/ja/db2/11.5?topic=tuning-collecting-reporting-performance-monitor-data)
db2monは指定した期間、DB全体の稼働状況を調べ、レポートを作成します。類似のレポートを出す方法には、MONREPORT.DBSUMMARYプロシージャーを使う方法もありますが、db2monの方がより多くの情報を集めます。
Db2 9.7以降、Db2の稼働状況を収集するためのおすすめの方法は、MON_GET_DATABASE()などの表関数をSQLで実行する方法になりました。この機能は、結果を得る際に、集約などSQLの機能が使える優れた方法ですが、多くのモニタリング項目が、DB活動化からの積算値であるため、モニタリング期間の前後で、この関数を使うSQLを実行し、結果データの差分を算出する必要がありました。また、これら表関数は、非常に多くの項目をレポートするので、可読性を高めるために行長を調整したり、モニタリング項目に精通する必要があったりしました。db2monはこの差分計算をしてくれるばかりか、可読性の高い詳細なレポートを出し、DBの中で何が起こっているのか教えてくれます。
何か性能の問題があった時に、製品サポートから取得をガイドされることもありますが、普段の稼働状態を監視し、チューニングの機会を探索するために常時集めても良いでしょう。
## 2. db2monの実行方法
db2monは、コマンドラインから実行するスクリプトです。Db2インスタンスのインスタンス・ホームの下、`$HOME/sqllib/samples/perf`にそのスクリプトはあります。
### 2-1. オンライン・モードとオフライン・モード
db2monの実行には、オンライン・モードとオフライン・モードがあります。db2monが終わった時、指定インターバルの差分を計算し、レポート作成までやってくれるのが、オンライン・モードです。一方、オフライン・モードでは、db2monは、モニター結果データをIXF形式で提供します。Db2が稼働している別環境（例：テスト環境）にこれらのIXFファイルを複製し、これらをIMPORTして、レポートを生成します。差分計算とレポート生成をやらない分、オフライン・モードの方がシステム負荷が小さいのは確かですが、実際は負荷の違いはごくわずかです。よく用いられるのはオンライン・モードです。
#### 2-1-1. オンライン・モードでの実行
以下の例のようにモニターしたいDBを指定します。コマンド実行後30秒間稼働を測定し、最後にレポートを出します。
```
db2mon.sh DB名 > レポート先ファイル
```
また第2引数に数字を指定することでモニタリング期間を指定できます。例えば５分間の稼働を知りたければ以下のようにします。
```
db2mon.sh DB名 300 > レポート先ファイル
```

#### 2-1-2. オフライン・モードでの実行
まずコマンド・ラインからモニター対象のDBに接続します。その後で、以下のようにdb2mon_export.sqlで提供されているSQLを実行します。
```
db2 -tvf db2mon_export.sql > メッセージ・ファイル
```
メッセージ・ファイルは、このスクリプトの実行ログです。モニター結果は複数のIXFファイルとして、現在の場所にエクスポートされます。
このIXFファイル群をどこかDb2の稼働環境に複製して以下を実行します。必要な表が作られてモニター・データがインポートされます。メッセージ・ファイルは、このスクリプトの実行ログです。
```
db2 –tvf db2mon_import.sql > メッセージ・ファイル
```
そして以下を実行することで、レポートを得ます。
```
db2 -tvf db2mon_report.sql > レポート先ファイル
```

## 3. 実行条件
db2monの利用のためには、以下を満たす必要があります。
* v9.7以降のサポートされたDb2を利用している。
* オンライン・モードの場合、ユーザー一時表スペースがある。（無ければ作ってくれます）
* 以下のモニタリング・スイッチがBASEまたはEXTENDEDに指定されている。（デフォルトはBASE）
　- MON_REQ_METRICS
　- MON_ACT_METRICS
　- MON_OBJ_METRICS

## 4. db2monのレポート解析
db2monはたくさんのモニタリング情報を返します。まずは主要なところから見ると良いでしょう。
### 4-1. DBのスループット
まず注目すべきは、DBレベルのスループット情報です。対象のDBにどんなアクセスがどれくらいのスループットで発生しているかわかります。
DB#THRUPとあるレポートです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/e828dd45-4bd4-e55c-2a9d-0de35ae67d6c.png)
##### 注目項目：
以下の項目に注目すると良いでしょう。
<dl>
<dt>ACT_PER_S</dt>
<dd>毎秒の処理件数</dd>
<dt>CMT_PER_S</dt>
<dd>毎秒のコミット件数を示します。ACT_PER_Sに対してこの項目が十分に小さくなければコミット頻度が高過ぎないか（自動コミットがONになっている等）疑います。</dd>
<dt>RB_PER_S<dt>
<dd>毎秒のロールバック件数を示します。ここが大きい場合、それが異常でないか確認します。</dd>
<dt>DDLCK_PER_S</dt>
<dd>毎秒のデッドロック発生件数</dd>
<dt>SEL_P_S</dt>
<dd>毎秒のSELECT実行数</dd>
<dt>UID_P_S</dt>
<dd>毎秒のUPDATE、INSERT, DELETE実行数を示します。先のSELECT実行数との割合を見ることで「読み取り／書き込み比率」がわかります。</dd>
<dt>ROWS_INS_P_S</dt> 
<dd>毎秒のINSERT行数</dd>
<dt>ROWS_UPD_P_S</dt> 
<dd>毎秒の更新行数</dd>
<dt>ROWS_RET_P_S</dt>
<dd>毎秒の戻り行数</dd>
<dt>ROWS_MOD_P_S</dt>
<dd>毎秒の修正行数</dd>
<dt>PKG_CACHE_INS_P_S</dt>
<dd>毎秒のパッケージ・キャッシュ挿入回数を示します。SQLのコンパイル回数が大き過ぎないか確認します。ホスト変数やパラメーターマーカーの有効利用（SQLの再利用促進）やパッケージ・キャッシュ拡大（メモリーヒット率向上）の余地がないか検討します。</dd>
<dt>P_RD_PER_S</dt>
<dd>毎秒の物理ディスク読み取りを示します。ディスク読み取りに注目したチューニングが有効か判断します。</dd>

### 4-2. クライアントの動作
このレポートからはアプリ側の処理時間とDB側の処理時間の割合を見ることができます。
DB#CLACTとあるレポートです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/0be7d373-6368-c137-49bd-69604329fe40.png)
１秒あたり１件以上のステートメントが流れる接続をアクティブな接続とみなします。
##### 注目項目：
以下の項目に注目すると良いでしょう。
<dl>
<dt>TOTAL_CLIENTS</dt>
<dd>接続数</dd>
<dt>ACTIVE_CLIENTS</dt>
<dd>アクティブな接続数</dd>
<dt>ACTIVE_CIWT_RQ_RATIO</dt>
<dd>アクティブな接続におけるアプリ側時間の割合を示します。ここが大きい（10以上）時はアプリ側ロジックの不良有無を確認します。</dd>

### 4-3. DB内時間の内訳
DB内の処理時間内訳を報告します。どこにチューニング余地があるか検討します。
 DB#TIMEBとあるレポートです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/49b30330-405e-2d39-76f9-3b0843f50b33.png)
##### 注目項目：
以下の項目に注目すると良いでしょう。
<dl>
<dt>TOTAL_RQST_TM</dt>
<dd>合計リクエスト時間</dd>
<dt>PCT_COMPILE</dt>
<dd>コンパイル時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_SECTION</dt>
<dd>SQL実行時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_SORT</dt>
<dd>ソート時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_COL</dt>
<dd>列指向データ処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_COL_SYNOP</dt>
<dd>シノプシス表（列指向データ処理時にアクセスされる内部表）処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_COMMIT</dt>
<dd>コミット処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_RBACK</dt>
<dd>ロールバック処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_CONN</dt>
<dd>DB接続処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合。</dd>
<dt>PCT_RTN_USR_CODE</dt>
<dd>UDFやストアード・プロシージャー内のユーザー・コードの処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_BACKUP</dt>
<dd>バックアップ処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_IDX_BLD</dt>
<dd>索引ビルド時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合。</dd>
<dt>PCT_RUNSTATS</dt>
<dd>統計情報収集時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合。</dd>
<dt>PCT_REORG</dt>
<dd>再編成処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_LOAD</dt>
<dd>データロード時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>

### 4-4. DB内待ち時間の内訳
DB内の処理時間内訳を報告します。どこかがボトルネックになっていないか確認します。
DB#WAITTとあるレポートです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/3b5e5a2b-0206-bbc4-9360-47640ebb5c37.png)
##### 注目項目：
以下の項目に注目すると良いでしょう。
<dl>
<dt>TOTAL_RQST_TM</dt>
<dd>合計リクエスト時間。</dd>
<dt>PCT_RQST_WAIT</dt>
<dd>待ち時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。ここの割合が大きくなっていないか見ることで、DBが健全に動いているか見極めることができます。</dd>
<dt>PCT_LOCK</dt>
<dd>ロック待ち時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_GLB_LOCK</dt>
<dd>グローバル・ロック待ち時間割合を示します（pureScaleのみ）。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_LATCH</dt>
<dd>ラッチ待ち時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_LG_DSK</dt>
<dd>ログディスクI/O待ち時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_LG_BUF</dt>
<dd>ログバッファー待ち時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_RCLM</dt>
<dd>リクレーム時間割合を示します（pureScaleのみ）。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_CF</dt>
<dd>CF待ち時間割合を示します（pureScaleのみ）。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_PFTCH</dt>
<dd>先読み待ち時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_DIAG</dt>
<dd>db2diag.log書き込み待ち時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_POOL_R</dt>
<dd>バッファープール読み取り時間割合を示します。表ページ/索引ページの物理読みとりとキャッシュヒットしてBuffer Poolだけを読んだ論理読みとりの合計時間の合計リクエスト時間（TOTAL_RQST_TM）に占める割合を示します。ここが大きな値を示す場合、読み取りが大きいSQLに着目します。</dd>
<dt>PCT_DIR_R</dt>
<dd>直接読み込み時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_DIR_W</dt>
<dd>直接書き込み時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>
<dt>PCT_FCM</dt>
<dd>FCM処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。DPF, BLU, イントラパラレルなどTable Queueを多く使う環境では、単に相手の処理を待っているだけで真のボトルネックは他の箇所かもしれないので、PCT_FCMが大きいからと言って直ちに問題ではない可能性があります。</dd>
<dt>PCT_TCPIP</dt>
<dd>DB内TCPIP処理時間割合を示します。合計リクエスト時間（TOTAL_RQST_TM）に占める割合です。</dd>

### 4-5. 処理時間の長いSQL
以降の２レポートはSQLステートメントのレベルで稼働状況をレポートします。特定のSQLステートメントが高負荷になっていないか見ることができます。
SQL#TOPEXECTとあるレポートです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/46686f8b-6623-6eb3-cd6b-c369ab24dc50.png)
##### 注目項目：
以下の項目に注目すると良いでしょう。
<dl>
<dt>AVG_COORD_EXEC_TIME</dt>
<dd>このSQLの平均実行時間です。実行時間の長いSQLを見つける。</dd>
<dt>PCT_COORD_STMT_EXEC_TIME</dt>
<dd>このSQL実行時間合計の全SQL実行時間に占める割合です</dd>
<dt>AVG_CPU_TIME, TOTAL_CPU_TIME</dt>
<dd>単位はμsです。このSQL実行時のCPU時間平均、CPU時間合計を示します。</dd>
<dt>PCT_WAIT_TIME</dt>
<dd>このSQL実行時の待ち時間割合を示します。全SQL実行時間に占める待ち時間の割合です。</dd>

まずはAVG_COORD_EXEC_TIMEとPCT_COORD_STMT_EXEC_TIMEを見て、ハイインパクトのSQLを見つけます。また、AVG_CPU_TIMEとTOTAL_CPU_TIMEに注目することでCPU消費の高いSQLを特定できます。特にPCT_WAIT_TIMEに注目です。こちらの項目からSQL応答時間全体に占める待ち時間を知ることができます。こちらが大きなSQLはチューニングによってボトルネックを解消することができれば効果も大きいと言えます。

### 4-6. 処理時間の長いSQLにおける待ち時間内訳
「4-4. DB内待ち時間の内訳」で示したレポートに類似していますが、こちらはSQLごとに待ち時間内訳をレポートします。対象のネーミングは一緒なので、4−４もご覧ください。
SQL#TOPWAITTとあるレポートです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/96509229-3ba3-d17e-49df-e64dd2c2f1e9.png)
このレポートから実行時間の長いSQLを特定し、その中から待ちの大きなSQLを特定します。そして、その待ちが何によって発生しているか確認します。一般的に何か特定の項目による待ちが３０％以上を示している時には、その項目についてのdb2monの他のレポートも確認すると良いでしょう。例えば、ロック待ちが大きな原因であると報告されている時は、ロック待ちについてのレポート（END#LOCKW）がロック待ちの状況を知るのに役立ちます。
### 4-7. よくあるボトルネック
Db2でよく見られるボトルネックは、db2monのレポートで見つけることができます。ここでは、Db2でよく見られるボトルネックとその際にdb2monのレポートに現れる兆候を見ていきます。
#### ログ書き込みが遅い
ログ書き込みがボトルネックになっているケースはよくあるケースです。
##### レポート上の兆候：
・PCT_LOG_DISKが大きい。
##### 確認すべき他の項目：
・DB#LOGWRのLOG_WRITE_TIME
・LTC#WAITTの特定ラッチ
##### アクション：
・ログ・ファイルシステム、ストレージの確認

DBではすべてのSQL書き込み（更新、削除、挿入）は基本的にコミット時にログに同期書き込みされます。ですから更新処理のあるDBでログの書き込みが遅いシステムでは、処理性能が望めません。DB#LOGWRレポートのLOG_WRITE_TIME_PER_IO_MSではログ書き込みのレイテンシーが毎秒何m秒であったかを示します。健全なシステムでは１ms前後のログ書き込みが一般的です。
#### ラッチ競合が大きい
ラッチ待ちのせいで性能が出ていないケースもしばしば発生します。
##### レポート上の兆候：
・PCT_LTCHが大きい。
##### 確認すべき他の項目：
・特定のSQLが遅くないか？アクセスプランは妥当か？
##### アクション：
・IBMサポートへコンタクトし指示を得ます。

ラッチとは同時に複数スレッドが同じ情報を更新してしまわないようにDb2内部で取られる構造で、勝手に取得・解放がなされます。
ラッチ競合が多発する時、LTC#WAITTレポートには、どんなラッチで競合を起こしているか報告されます。ですが、ラッチの情報はあまりに詳細で、外部公開されていません。ユーザー側でラッチの解析を進めるのは困難でしょう。IBMサポートの方でこちらを見ることになります。

#### ディスクI/Oが遅い
DBは巨大なデータを管理するシステムですから、必要以上にディスク・アクセスが起きていたり、ディスク・アクセスの性能が悪いとDBの性能も劣化します。
##### レポート上の兆候：
・PCT_POOL_R, PCT_DIRECT_R, PCT_DIRECT_Wが大きい。
##### 確認すべき他の項目：
・BPL#SIZESが示すバッファープール・サイズ
・BPL#HITRAが示すバッファープール・ヒット率
・特定のSQLが遅くないか？アクセスプランは妥当か？
・SQL#TOPROWSが示すROWS_READとROWS_RETURNEDの比率（対象行の特定に大量行を読んでないか）
##### アクション：
・バッファープール拡張
・LOBデータのインライン化
・アクセスプラン確認
・表スペースが利用するファイルシステム、ストレージの確認

ディスクが遅い時、バッファープール・ページのラッチ待ちも合わせて出ているかもしれません。Db2はディスクからバッファープールへデータを読み込むとき、当該ページにラッチを取得します。
#### SQLが重い（CPU消費が高い）
特定の重いSQLがサーバーの資源を大きく消費している事例もしばしば発生します。
##### レポート上の兆候：
・特定のSQLについてTOTAL_CPU_TIMEが他より高い。
##### 確認すべき他項目：
・SQL#TOPSORTのPCT_SORT_TIME
・SQL#TOPIOSTAのAVG_D_LRD
##### アクション：
・アクセスプラン確認

TOTAL_CPU_TIME/1000がCOORD_STMT_EXEC_TIMEの多くを占めているようなSQLはCPUバウンドのSQLだと言えます。
また、一般的に大量行を処理するSQLは多くのCPUを消費します。AVG_ROWS_RET(結果行の数)よりAVG_ROWS_READ（読み取り行の数）の方が大幅に大きいようなSQLは、結果を得るのに大量の読み取りが必要であることを示します。OLTPであったなら、目的の行をピンポイントでアクセスするようなSQLが中心だと思うので、索引をきちんと使っているかどうか確認します。
#### ロック競合
##### レポート上の兆候：
・PCT_LOCKが大きい。
##### 確認すべき他項目：
・START#LOCKWやEND#LOCKWレポート
##### アクション：
・アプリの改善可能性検討（分離レベルの変更など）
・アクセスプラン確認
## 5. まとめ
db2monは、Db2の稼働状況を把握する優れたツールです。Db2に何らかの性能問題が起きた時はもちろん、普段の状況監視にも利用可能です。
db2monはコマンドラインから実行可能であり、出力レポートもテキストベースですから、grepやawkなどを使って好きに加工できます。GUIをお望みの場合はIBM Data Server Manager等の利用が望ましいでしょう
## 参考文献
[・db2mon script for monitoring performance](https://www.ibm.com/support/pages/db2mon-script-monitoring-performance)
[・db2mon によるパフォーマンス・モニター・データの収集とレポート作成](https://www.ibm.com/docs/ja/db2/11.5?topic=tuning-collecting-reporting-performance-monitor-data)