オンプレにあったバッチサーバをAWSへ移行する際、極端に性能劣化がが発生した際の対策を以下まとめます。直接的な原因はオンプレに残すDBサーバ間のレイテンシ増加(約2~3ms→17~20ms)にありました。
当初からレイテンシに原因がある事を疑いTCPウィンドウサイズの調整やJDBCのフェッチサイズの調整を試みましたが思うような結果とならず戸惑ったのですが、Db2 for iでは他のDBにはないblock sizeとprefetchという設定も合わせて調整しないといけない事わかりました。特にprefetchは重要です。
1. 基本概念
- block size
- サーバ→クライアント転送時の「1ブロックのサイズ(バイト数)」
- デフォルト:32KB
- 大きくすると1回の転送で多くのデータを送れるため、RTT(往復回数)が減る
- 設定方法:接続URLまたは接続プロパティで
block size=値
- prefetch
- サーバ側が「事前にまとめて読み込む行数」
- デフォルト:10行(非常に小さい)
- 大きくするとサーバがまとめて返す行数が増え、RTTが減る
- 設定方法:接続URLまたは接続プロパティで
prefetch=値 - Db2 for i 独自の仕組み(他のDBには存在しない)
- fetchSize (JDBC API)
- クライアントが「一度に欲しい行数」を指定する
Statement.setFetchSize(int rows)で設定可能prefetchが小さいと効果が薄れるため、両者を揃えることが重要
2. 効果的な使い方
- fetchSize と prefetch を同じ値にする
- 例:
fetchSize=10000+prefetch=10000 - 「1フェッチ=1RTT」に近づき、効率最大化
- 例:
- block size を拡張する
- デフォルト32KBでは細切れ転送になる
- 128KB〜512KB程度に設定すると効果的
- 例:
block size=256000(256KB)
- メモリとのバランス
- prefetch を大きくするとサーバ側メモリ消費が増える
- 段階的に値を増やして最適値を探すことが推奨
3. 設定例(接続URL)
String url = "jdbc:as400://myhost;"
+ "prefetch=10000;" // サーバ側で1万行を事前に読み込む
+ "block size=256000"; // 転送単位を256KBに設定
Connection conn = DriverManager.getConnection(url, "myuser", "mypassword");
PreparedStatement ps = conn.prepareStatement("SELECT * FROM customer ORDER BY sustid");
ps.setFetchSize(10000); // クライアント側も1万行を要求
ResultSet rs = ps.executeQuery();
4. 他DBとの違い
- Oracle:
似たものとして、defaultRowPrefetchというものが ありますが、これはJDBCドライバ側の最適化法で、Db2 for iのようにサーバ側の設定ではありません。 - PostgreSQL / MySQL / SQL Server:
setFetchSize()がカーソル制御に使われる。prefetchプロパティは存在しない - Db2 LUW (Linux/Unix/Windows):
prefetchはページ単位のI/O最適化であり、JDBC接続URLで指定するものではない
👉 「prefetch=行数」という接続プロパティは Db2 for i 独自の仕組み。他のDBには存在しないため、AS400特有のチューニングポイントとなる。

