目的
IBM CloudのDb2 on Cloudは、オンプレミスに比べてINSERT性能が非常に悪いと感じる場合があります。原因としては、Db2 on Cloudはクラウドのネットワーク越しに存在するため、ネットワーク遅延の影響を受けることが1つ。もう1つですが、Db2 on CloudはHADR構成がとられており、かつ、スタンバイ機の1台はSYNCモードになっています。つまり、1回のコミットに対して、プライマリとスタンバイ2つのデータベースに更新が反映されてはじめて応答が返ってくる仕組みになっているためです。
今回は少しでも性能を上げるための方策を検証してみます。
計測
計測方法
テスト用のCSVをIMPORTコマンドで投入する際の時間を測ります。IMPORTコマンドは内部的にはINSERT文として処理されます。
計測用DDLです。
CREATE TABLE PERFTEST (
C1 INT NOT NULL GENERATED ALWAYS AS IDENTITY,
C2 DECIMAL(10,0),
C3 DECIMAL(10,0),
C4 DECIMAL(10,0),
C5 DECIMAL(10,0),
C6 DECIMAL(10,0),
C7 DECIMAL(10,0),
C8 DECIMAL(10,0),
C9 DECIMAL(10,0),
C10 DECIMAL(10,0),
PRIMARY KEY(C1)
);
インポート用テストデータを生成します。10万行用意します。
#!/usr/bin/perl
$max = 100000;
for ($i = 0; $i < $max; $i++) {
printf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", $i, $i,$i,$i,$i,$i,$i,$i,$i);
}
計測
チューニング前
1万行ごとにコミットしてデータをインポートします。インポートは内部的には1行ごとにINSERTする処理に変換されます。
$ time db2 "import from 100000.csv of del commitcount 10000 insert into perftest (c2,c3,c4,c5,c6,c7,c8,c9,c10)"
Db2 on Cloud | Db2(ローカル) | |
---|---|---|
所要時間 | 6m57s | 0m29s |
スループット | 241行/秒 | 3421行/秒 |
圧倒的な差が出ていることがわかります。
複数行を一括してインサート
Db2のIMPORTコマンドではmodified by compondを指定することで、複数のINSERTを一括して実行することができます。JDBCではStatement.addBatch()とexecuteBatch()に相当します。compoundの最大値である100行を指定して実行します。
$ time db2 "import from 100000.csv of del modified by compound=100 commitcount 10000 insert into perftest (c2,c3,c4,c5,c6,c7,c8,c9,c10)"
Db2 on Cloud | Db2(ローカル) | |
---|---|---|
所要時間 | 1m53s | 0m22s |
スループット | 885行/秒 | 4545行/秒 |
ローカルでは1.3倍、Db2 on Cloudでは3.6倍ほどの性能向上が見られました。それでもローカルとは1桁違います。
引き続き、他にいい策はないか検討してみます。
注意
本検証の結果ですが、実行時間の絶対値に意味はありません。modified by compound以外で処理性能を上げる方法はいくつかあります。例えば自動生成列のキャッシュサイズを大きくする、テーブルにAPPEND ONを付与する等です。本検証はあくまでmodified by compoundの効果を見ているだけということは注意ください。