こんばんは!ヒカリです。
Webエンジニアを目指してプログラミングを勉強している初心者の方向けに情報を発信しています。
今流行の仮想通貨を自動売買してみました!
リモートワークでおすすめのグッズ紹介してみました!
今回はこのような質問をいただきました。
負荷試験用に大量のデータを投入する必要があるんだけどどうしたら良い?
大量のデータを投入するときは考えてからやらないと、かなり時間がかかってしまいます。
そこで今回はこちらの質問について解説していきます!
環境
- 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万回ループさせるのはさすがに無理がありますね…
何回かに分けて実行したり、停止したらその値からリスタートしたりする必要があるかもしれません。
やりやすいように設定したり、処理を書き換えてみたりしてみてください!