ふり
負荷試験用に大量のデータを投入しないと…
ということで今回は800万レコードを追加するためのコードを書いてみました。
環境
- Java 11
- Play Framework 2.6
- IntelliJ IDEA ULTIMATE 2019.2
最初はエンティティを使って1件ずつ登録する処理でやってみたのですが、単純計算で240時間かかりそうだったので修正…まぁそうなりますよね笑
そこでネイティブクエリを使って1つのクエリで10,000レコード登録するような処理に変更しました。
これで
30レコード/秒 → 10,000レコード/秒
くらいの変化がありました。
このとき使ったコードを残しておきます。
エンティティを使って1件ずつ登録!
ネイティブクエリを使って1つのクエリで10,000レコード登録!
ネイティブクエリを使って大量にデータを登録する処理!
追加したいレコード数分ループさせて、10,000回に1回コミットします。
10,000レコードを一括で登録するSQL文を作ってる感じです。
String query = "INSERT INTO table_name (column_name1 , column_name2, column_name3, column_name4) VALUES";
StringJoiner joiner = new StringJoiner(",");
for (double i = 1; i <= 8000000; i++) {
joiner.add("( 'value1', 'value2', 'value3', 'value4' )");
if (i % 10000 == 0) {
System.out.println(i);
String values = joiner.toString();
Jpa.jpa.withTransaction(() -> {
Jpa.em().createNativeQuery(query + values).executeUpdate();
});
joiner = new StringJoiner(",");
}
}
- 1行目でテーブルの情報を指定してください。
- 3行目でループ回数を指定してください。
ループ回数によって6行目の条件を変更したほうが良いと思います。 - 4行目で追加する情報を指定してください。
ユニークな値が必要な場合はi
を使うことでユニークになります。 - 10〜12行目はORMによって違うと思うので書き換えてください。
トランザクションを張ってネイティブクエリ(query + values
)を実行しています。
あとがき
私が実行したときは2回ほどメモリ不足で停止してしまいました。
800万回ループさせるのはさすがに無理がありますね…
何回かに分けて実行したり、停止したらその値からリスタートしたりする必要があるかもしれません。
やりやすいように設定したり、処理を書き換えてみたりしてみてください!
ABOUT ME