批量更新方式与对比

现有需求:我要基于用户id, 去批量用户username;

例如 id =1 ,username = ABC ;

id =2 ,username = BCD ;

那么更新sql就是 update table_name set username = 'ABC' where id = 1;

如果是批量,很多人就会在代码的xml里面去动态拼接,一次性提交多条sql

<foreach collection="list" item="item" separator=";">
UPDATE table_name
set username = #{item.username}
where id = #{item.id}
</foreach>

这种操作当然可以,但是性能肯定不行。

所以除了这种批量更新的方式,你还知道几种呢?

其实还有可以通过CASE WHEN ,INNER JON + 临时表的方式

那就把三种方式都尝试下吧。

1、XML动态拼接

就是我上面说的,大部分都是这样写的

2、Case When

还是拿上面哪个例子来写,先写原生sql

UPDATE table_name
SET username = CASE id
WHEN 1 THEN 'ABC'
WHEN 2 THEN 'BCD'

END
WHERE mobile IN(1,2)

-- 单条件
<update id="updateBatch" parameterType="java.util.List">
update mydata_table
<trim prefix="set" suffixOverrides=",">
<trim prefix="status =case" suffix="end,">
<foreach collection="list" item="item" index="index">
<if test="item.status !=null ">
when id=#{item.id} then #{item.status}
</if>
</foreach>
</trim>
</trim>
where id in
<foreach collection="list" index="index" item="item" separator="," open="(" close=")">
#{item.id,jdbcType=BIGINT}
</foreach>
</update>

-- 多条件
<update id="updateBatch" parameterType="java.util.List">
update demo_table
<trim prefix="set" suffixOverrides=",">
status=
<foreach collection="list" item="item" open="case " close=" end,">
when field2=#{item.field2} and company_id=#{item.field3} then #{item.status}
</foreach>
create_time =
<foreach collection="list" item="item" open="case " close=" end,">
when field2=#{item.field2} and company_id=#{item.field3} then
<choose>
<when test="item.createTime!=null">
#{item.createTime}
</when>
<otherwise>now()</otherwise>
</choose>
</foreach>
</trim>
WHERE
<foreach collection="list" item="item" open="( " separator=") or (" close=" )">
device_num=#{item.field2} and company_id=#{item.field3}
</foreach>
</update>

这种相当于一条sql更新多条记录了。但是这种情况会有几个缺点,更新多个多字段的时候,就要有多个

CASE WHEN。 这就会导致长度很长。所以注定不能一次更新很多,建议每次更新2000条。

3、INNER JOIN + 临时表

-- 1、创表
create table xxx{}
-- 2、批量插入数据
insert into table values (1,A),(2,B);
-- 3、连表更新
update table1 t1
inner join table2 t2 on t1.id = t2.id and 更新条件
set t1.name = t2.name
-- 4、 删除表
drop table xxx;

这种的比较适合大量的数据更新,因为不涉及长度问题。(大量数据更新,一定要考量场景,做好监控记录)

其实还有一种轻量化的方式,就是用inner join 去连一个内置的临时表

UPDATE table_name t1
INNER JOIN (SELECT 1 as id, 'ABC' as username
UNION ALL
SELECT 2 as id, 'BCD' as username)
AS t2 ON t1.id = t2.id
SET t1.username = t2.username

我们找1000条数据测试下结果

|----------|--------|-----------|------------------|
| 方式 | 拼接一次提交 | case when | join + union all |
| 执行时间(ms) | 16689 | 661 | 542 |
| 平均耗时(ms) | 16.6 | 0.66 | 0.52 |
| 优点 | 简单 | 性能好 | 性能好 |
| 缺点 | 性能差 | 长度受限 | 长度受限 |

相关推荐
NaMM CHIN17 分钟前
SQL sever数据导入导出实验
数据库·sql·oracle
山峰哥1 小时前
告别“点点点”:AI 如何重构我们的测试体系与质量防线
服务器·汇编·数据库·人工智能·性能优化·重构
shark22222222 小时前
MySQL 与 Redis 的数据一致性问题
数据库·redis·mysql
Elastic 中国社区官方博客2 小时前
LINQ 到 ES|QL:使用 C# 查询 Elasticsearch
大数据·数据库·sql·elasticsearch·搜索引擎·全文检索·linq
Code-Porter2 小时前
记录关于Flutter ObjectBox数据库使用ObjectBoxBrowser插件,在同一个局域网内电脑无法访问查看数据问题
android·数据库·flutter·dart
AI精钢2 小时前
什么是面向 Agent 的 LLM?从 Qwen3.6-Plus 看大模型的新分水岭
网络·数据库·人工智能·云原生·aigc
xcLeigh2 小时前
KES数据库从入门到精通:零基础起步,全面掌握KES核心基础
大数据·数据库·sql·数据分析·国产数据库·kes
yj_xqj2 小时前
openGauss 数据库报错“failed: To0 many open files”
运维·数据库
※DX3906※2 小时前
SpringBoot之旅5| 快速上手SpringAOP、深入刨析动态/静态两种代理模式
java·数据库·spring boot·后端·spring·java-ee·代理模式
千桐科技2 小时前
数据仓库 vs 数据中台:从“数据库的豪华升级版”到“企业的数据操作系统”
数据库·数据仓库·数据治理·数据中台·数据资产·数据服务·qdata