在平常的开发工作中,我们经常需要批量更新数据,业务需要每次批量更新几千条数据,采用 update foreach 写法的时候,接口响应 10s 左右,优化后,采用 update ... case when 写法,接口响应 2s 左右。今天来总结一下两种常见的写法使用场景及性能比较。
一:foreach 批量更新
<update id="batchUpdateStudentScore"><foreach collection="list" item="item" separator=";">UPDATE student_scoreSET score = #{item.score}, grade = #{item.grade} <!-- 修复原写法的语法错误 -->WHERE id = #{item.id}</foreach>
</update>
生成的执行sql如下:
UPDATE student_score SET score = 85, grade = 'A' WHERE id = 1;
UPDATE student_score SET score = 70, grade = 'B' WHERE id = 2;
UPDATE student_score SET score = 95, grade = 'A+' WHERE id = 3;
二:update ... case when 批量更新
<update id="batchUpdateStudentScore">UPDATE student_scoreSET score = CASE <foreach collection="list" item="item" separator="">WHEN id = #{item.id} THEN #{item.score}</foreach>ELSE score END,grade = CASE <foreach collection="list" item="item" separator="">WHEN id = #{item.id} THEN #{item.grade}</foreach>ELSE grade ENDWHERE id IN <foreach collection="list" item="item" open="(" separator="," close=")">#{item.id}</foreach>
</update>
生成的执行sql如下:
UPDATE student_score
SET score = CASE WHEN id = 1 THEN 85 WHEN id = 2 THEN 70 WHEN id = 3 THEN 95 ELSE score END,grade = CASE WHEN id = 1 THEN 'A' WHEN id = 2 THEN 'B' WHEN id = 3 THEN 'A+' ELSE grade END
WHERE id IN (1, 2, 3);
三:对比总结
维度 |
|
|
SQL 语句数量 | N 条(N = 列表长度) | 1 条 |
数据库交互次数 | N 次 | 1 次 |
原子性 | 依赖事务 | 天然原子性 |
适用数据量 | 50 条 | 50 条 - 5000 条,数量量超过 1000 时建议分批 |
网络传输量 | 大(多次传输 SQL) | 小(单次传输长 SQL) |
总结:
foreach 本质都是循环执行多条 SQL,效率远低于 case when,当一次批量更新的数据大于10条时,建议采用 case when 写法。
四:使用场景
1:
foreach 批量更新适用场景
a:如单次更新 10 条以内,循环的性能损耗可忽略。
b:每条记录更新需单独控制事务(如某条失败不影响其他)。
注意:需确保数据库连接池允许批量执行多条 SQL(如 MySQL 需开启allowMultiQueries=true
)。数据量过大(如 N>1000)可能导致连接超时或 SQL 注入风险增加。
2. update...case when 适用场景
a:单次更新 50-1000 条,需减少数据库交互次数。
b:仅需根据主键(id)匹配更新值,无需额外计算。
c:同时更新多个字段时,case when 比 foreach 更简洁高效。
注意:必须加 where id in (...)
,否则会全表扫描(未匹配记录会被ELSE
保持原值,但浪费性能)。若 N>1000,生成的 SQL 可能过长,建议分批次(如每 500 条一批)。
五:总结
数据量小于 50 条时,优先采用 update foreach,写法简单,性能也可以。当大于 50 条,甚至上千条时,采用 update...case when 写法,执行效率高,比 update foreach 写法性能提升几倍。但是如果一次更新几千条数据,建议分批执行,比如每500条执行一次。