Spring JPA 中批量插入和更新是使用 SimpleJpaRepository#saveAll,saveAll 会循环调用 save 方法,save 方法会根据实体 id 查找记录,记录存在则更新,不存在则插入。n 个实体需要执行 2n 条语句,因而效率较低。
1 | java复制代码@Transactional |
注:id 为基本类型且为 null 时,会直接插入记录,只执行 n 条语句。
此文中,将在主键自增的前提下,以借助 druid 监控,探讨 Spring JPA 批量插入与更新优化思路。
批量插入
使用 SimpleJpaRepository#saveAll,插入 5k 条记录。
总共执行事务 5000*2 次,用时 543 s。
Hibernate 本身支持批量执行,通过 spring.jpa.properties.hibernate.jdbc.batch_size 指定批处理的容量。
共执行事务 5000+5 次,用时 439 s。
利用 EntityManager 批量插入 5k 条记录。
1 | ini复制代码private <S extends T> void batchExecute(Iterable<S> s, Consumer<S> consumer) { |
总共执行事务 5 次,用时 255 s,和 SimpleJpaRepository#saveAll 相比,节省了查询的性能消耗。
通过拼接 SQL 语句的方式,使用一条语句插入多条记录。
1 | scss复制代码public void insertUsingConcat() { |
执行一次事务,用时 0.2 s。
拼接语句需要注意 sql 语句长度限制,可以通过 show VARIABLES WHERE Variable_name LIKE 'max_allowed_packet';
查询,这是 Server 一次接受的数据包大小,通过 my.ini 配置。
批量更新
批量更新和批量插入类似,也是四种写法,结论也一致。区别仅在于 sql 写法:
1 | less复制代码@PutMapping("/concatUpdateClause") |
本文转载自: 掘金