Overview
spring jdbc使っていて、batchUpdateというのがあることに気がついた。
ドキュメントを見ていると複数のデータを登録していくときは効率的っぽいことが書いてあったけど、どう効率的なのかがよくわからなかったのでし らべてみた
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html#batchUpdate-java.lang.String-org.springframework.jdbc.core.BatchPreparedStatementSetter- https://docs.spring.io/spring-framework/docs/3.0.0.RC3/spring-framework-reference/html/ch12s04.html
実際の動きを確認
最初にこんな感じのテーブルと、
CREATE TABLE product(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
division INT(10) NOT NULL,
created DATETIME NOT NULL,
name VARCHAR(20) NOT NULL,
PRIMARY KEY(id),
UNIQUE KEY uk_product (division, created)
);
こんな感じのコードを用意してどんなSQLが発行されるか試してみた
@Repository
public class ProductRepositoryImpl implements ProductRepository {
private final NamedParameterJdbcTemplate jdbcTemplate;
public ProductRepositoryImpl(NamedParameterJdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void batchInsert(List<Product> producs) {
String sql = "INSERT INTO product (division, created, name) "
"VALUES(:division, :created, :name)";
jdbcTemplate.batchUpdate(sql,
producs.stream()
.map(p ->
new MapSqlParameterSource()
.addValue("division", p.getDivision(), Types.INTEGER)
.addValue("created", p.getCreated(), Types.TIMESTAMP)
.addValue("name", p.getName(), Types.CHAR)
) .toArray(SqlParameterSource[]::new)
);
}
}
上記のコードを実行して、Mysqlのログから実際発行されたSQLを確認してみる
| 2019-06-08 18:44:31.192892 | test[test] @ [xxx.xx.xx.xx] | 69 | 0 | Query | INSERT INTO product (division, created, name) VALUES(1, '2019-06-08 18:44:28.159', 'aa')
| 2019-06-08 18:44:31.196375 | test[test] @ [xxx.xx.xx.xx] | 69 | 0 | Query | INSERT INTO product (division, created, name) VALUES(1, '2019-06-08 18:44:29.659', 'bb')
まぁそりゃそうだろ感があるが、普通にInsert文が2発飛んでいる というわけで、Spring JDBCのコードを追っていく。
Spring JDBCのコードを確認
上記のコードを読んでいくと、PreparedStatement#addBatchでSQLを追加していき、PreparedStatement#executeBatchでまとめてDBへ送信しているようだった。
どうやら、一度にクエリをDBへ送るという点で、普通にupdateをくるくる回すよりパフォーマンスが優れているということのようだ。
……と、調べ終わってからそれっぽいことが書いてあるドキュメント(Spring JDBCのじゃないけど)を見つけた。 https://docs.oracle.com/javase/jp/1.3/guide/jdbc/spec2/jdbc2.1.frame6.html