关于 mybatis 批量更新 updateBatch 的两种方式对比,<foreach> 真的慢吗?

批量有比较常用的两种方法:
方式1 case when:

	UPDATE t_eipo_stock_subscribe_order 
SET publish_id =
CASE
		
		WHEN id = 20253165 THEN
		20190201 
		WHEN id = 20253166 THEN
		20190201 
		WHEN id = 20253167 THEN
		20190201 
	END,
	capital_id =
CASE
		WHEN id = 20253165 THEN
		2020000079 
		WHEN id = 20253166 THEN
		2020000079 
		WHEN id = 20253167 THEN
		2020000079 
	END,
case when xxx = ?? then (伪代码) end		
WHERE
	id IN ( 20253165, 20253166, 20253167 )
	
对应的 mybatis 长这样
update id = id="updateBatch" parameterType="java.util.List">
<trim prefix="set" suffixOverrides=",">
      <trim prefix="publish_id = case" suffix="end,">
        <foreach collection="list" index="index" item="item">
          when id = #{item.id,jdbcType=BIGINT} then #{item.publishId,jdbcType=BIGINT}
        </foreach>
      </trim>
	<trim> 
		......
	</trim>
</trim>
where id in
    <foreach close=")" collection="list" item="item" open="(" separator=", ">
      #{item.id,jdbcType=BIGINT}
    </foreach>

方式2 foreach:


update table_name set publish_id = 20202024, operator_no = '101564453001421964', is_sub = 0, updated_at = '2022-1-3 17:21:42' where id = 1 ; 
update table_name set publish_id = 20202024, operator_no = '101587017453312930', is_sub = 0, updated_at = '2022-1-3 17:21:42' where id = 2 ; 

对应的 xml 长这样:

 <update id="updateForch" parameterType="java.util.List" >
        <foreach collection="list" item="item" index="index" open="" close="" separator=";">
            update standard_relation
            <set >
                <if test="item.standardFromUuid != null" >
                    standard_from_uuid = #{item.standardFromUuid,jdbcType=VARCHAR},
                </if>
                <if test="item.standardToUuid != null" >
                    standard_to_uuid = #{item.standardToUuid,jdbcType=VARCHAR},
                </if>
                <if test="item.gmtModified != null" >
                    gmt_modified = #{item.gmtModified,jdbcType=TIMESTAMP},
                </if>
            </set>
            where id = #{item.id,jdbcType=BIGINT}
        </foreach>
    </update>

测试方式,
从数据库里读取数据 然后 进行 update 操作 , 测试结果如下:
注意:
foreach 方式(方式2) 要想成功,需要在db链接url后面带一个参数 &allowMultiQueries=true
即: jdbc:mysql://localhost:3306/mysqlTest?characterEncoding=utf-8&allowMultiQueries=true
更新100条
在这里插入图片描述

更新500条

在这里插入图片描述

更新 1000条
在这里插入图片描述

更新 5000条

在这里插入图片描述
个人总结:
可见 foreach 方式并不一定比 case when 方式慢, 甚至数据量 大时反而更快.
为什么?
首先说明, 我测试用的表 总共 字段 大概有 40多个 , 所以不管用什么方式, mybatis 都要对 xml 种的标签进行解析. 问题就在这里了 ,
case when 方式 在解析 sql 语句时 每个字段 都要 for 对 传的 list 进行遍历 , 再解析程一条很长的 sql 交给 mysql 执行. 在数据量和字段上来时, 解析花费的时间 类似 笛卡尔乘积,
foreach 方式 它解析 sql 是 多条 以 “;” 结尾的 update 语句, 然后统一 提交给 mysql 执行 , 数据量大时 和 字段比较多时, 优势就体现出来了.

所以, 在 字段比较多的情况下 且数据量超过 1000 条 用 foreach 会比较快 , 字段比较少 用 case when 方式 ,
在数据量非常大时 , 批量操作时 最好 对 list 进行分批 进行 批量操作

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值