saveAll 为什么这么慢?hibernate.jdbc.batch_size 为什么没效果?batchUpdate 真的是批量吗?rewriteBatchedStatements 到底改变了什么?这篇用服务端的 Com_insert 与 Com_select 计数,把 10 种组合逐个测了一遍。
JdbcTemplate 循环里一行一个 update(同一个事务):中位 460 ms(432~727);服务端 Com_insert +10000,Com_select +0;表里 10000 行 JdbcTemplate.batchUpdate(sql, List<Object[]>)(同一个事务):中位 366 ms(351~435);服务端 Com_insert +10000,Com_select +1;表里 10000 行 JPA saveAll,主键 IDENTITY(已设 hibernate.jdbc.batch_size=500):中位 602 ms(558~816);服务端 Com_insert +10000,Com_select +0;表里 10000 行 JPA saveAll,手动指定主键 + Persistable.isNew()=true(batch_size=500):中位 518 ms(418~628);服务端 Com_insert +10000,Com_select +20;表里 10000 行 JPA saveAll,手动指定主键但不实现 Persistable(batch_size=500):中位 1008 ms(913~1191);服务端 Com_insert +10000,Com_select +10020;表里 10000 行
五种写法服务端都是 10000 条 INSERT;IDENTITY 让 batch_size 失效;手动主键不实现 Persistable 会多出 10020 次 select。
JdbcTemplate 循环里一行一个 update(同一个事务):中位 441 ms(412~593);服务端 Com_insert +10000,Com_select +0;表里 10000 行 JdbcTemplate.batchUpdate(sql, List<Object[]>)(同一个事务):中位 45 ms(45~54);服务端 Com_insert +1,Com_select +1;表里 10000 行 JPA saveAll,主键 IDENTITY(已设 hibernate.jdbc.batch_size=500):中位 583 ms(530~754);服务端 Com_insert +10000,Com_select +0;表里 10000 行 JPA saveAll,手动指定主键 + Persistable.isNew()=true(batch_size=500):中位 94 ms(90~127);服务端 Com_insert +20,Com_select +20;表里 10000 行 JPA saveAll,手动指定主键但不实现 Persistable(batch_size=500):中位 653 ms(648~876);服务端 Com_insert +20,Com_select +10020;表里 10000 行
batchUpdate 合并成 1 条多行 insert;saveAll(手动主键 + Persistable)合并成 20 条;IDENTITY 不受影响。