JavaからDBの複数レコードを更新する処理を実装していて、ふと疑問に思いました。
更新対象が数件しかない場合でも、まとめてUPDATEする処理にしたほうがいいのか?
大量データなら、1件ずつSQLを発行するよりバッチ更新したほうが速そうです。
でも、数件しかない場合はどうなのでしょうか。
今回は「通常のUPDATE」「JDBCのバッチ更新」「1つのSQLで複数行を更新する方法」の違いを整理します。
1件ずつUPDATEする場合
たとえば、Javaから複数件を更新するとします。
for (User user : users) {
jdbcTemplate.update(
"UPDATE users SET status = ? WHERE id = ?",
user.getStatus(),
user.getId()
);
}
この場合、更新対象ごとにSQLを実行します。
3件ならイメージとしては、
Java → DB:UPDATE 1
Java → DB:UPDATE 2
Java → DB:UPDATE 3
となります。
実際にはコネクションプールやJDBCドライバなども関係するので、単純にこの図だけで性能が決まるわけではありません。
ただ、「SQLを実行する回数が増える」という点は押さえておく必要があります。
batchUpdateを使う場合
SpringのJdbcTemplateなら、batchUpdateを使って複数件の更新をまとめてJDBCに渡すことができます。
jdbcTemplate.batchUpdate(
"UPDATE users SET status = ? WHERE id = ?",
batchArgs
);
大量の更新を行う場合は、1件ずつ個別に処理するより効率がよくなる可能性があります。
特に件数が増えてくると、DBとのやり取りやSQL実行に伴うオーバーヘッドを抑えられるメリットが出てきます。
ただ、ここで気になったのが、
そもそも更新対象が数件しかない場合、バッチにする意味はあるのか?
という点です。
少数件ならbatchUpdateのメリットは小さい
たとえば更新対象が3件しかない場合。
通常UPDATEなら3回更新します。
一方、batchUpdateを使う場合は、複数件をまとめて渡すためのパラメータを準備する必要があります。
つまりバッチ更新にも、
- 更新データをまとめる
- バッチ用のパラメータを組み立てる
- JDBCドライバ側でバッチとして処理する
といった処理があります。
そのため、数件程度の更新では、バッチ化による性能改善がほとんど見えないことがあります。
だからといって、
少数件ならbatchUpdateのほうが遅い
と断定できるわけでもありません。
DB、JDBCドライバ、ネットワーク、SQLの内容などによって結果は変わります。
重要なのは、
バッチ更新は無料で高速化できる仕組みではなく、件数が増えたときにメリットが大きくなりやすい
ということだと思います。
1つのSQLで更新できるなら話は別
もう一つ区別しておきたいのが、
「JDBCのバッチ更新」
と
「1つのUPDATE文で複数行を更新する」
ことです。
たとえば、複数のIDをすべて同じステータスに変更するなら、
UPDATE users
SET status = 'DONE'
WHERE id IN (1, 2, 3);
と書けます。
これはJavaから3回UPDATEするのではなく、SQLそのものが1回です。
同じ更新内容を適用できるなら、少数件でもこちらのほうがシンプルになる場合があります。
結局、少数件ならどうする?
今回調べて整理した結果、私は次のように考えることにしました。
| 状況 | 選択肢 |
|---|---|
| 数件程度で更新内容がそれぞれ違う | 通常UPDATEで十分 |
| 数件程度で同じ内容に更新できる | 1つのUPDATE文を検討 |
| 件数が多い | batchUpdateを検討 |
| 性能要件が厳しい | 実際に計測して判断 |
特に大事だと思ったのは、件数だけを見て決めないことです。
たとえば10件だから通常UPDATE、100件だからバッチ更新、という絶対的な境界があるわけではありません。
ネットワークの遅延やSQL自体の重さによっても結果は変わります。
まとめ
最初は、
複数件なら、とりあえずまとめて更新したほうが速いのでは?
と思っていました。
でも実際には、少数件ならバッチ更新によるメリットは小さく、通常のUPDATEでも十分なケースがあります。
逆に件数が増えてくると、DBとのやり取りを効率化できるバッチ更新のメリットが大きくなってきます。
また、同じ内容を複数行に適用できるのであれば、バッチ更新より先に「そもそも1つのSQLにできないか」を考える余地もあります。
今回整理してみて、
「複数件だからバッチ更新」ではなく、更新件数・SQLの形・DBとのやり取り・コードの複雑さを見て選ぶ
という考え方が大事だと分かりました。