Mybatis批量更新优化方案
目录
前言
今天在对接客户接口的时候,对方同步数据到我们系统,涉及到数据批量更新,插入的逻辑,出于性能方面的考虑,决定对自己写的逻辑进行优化,下面对几种优化方案进行总结。
需求
同步部门数据到mysql数据库,响应示例:
拿到json后,如果数据库不存在部门数据,则进行插入操作;存在部门数据,则做修改操作。这里演示存在数据进行修改操作。
原方案
使用mybatis-plus的saveOrUpdateBatch接口
修改部分代码逻辑:
启动项目进行测试:
经测试,接收的数据30条左右,耗时 1082ms ,显然达不到预期的性能要求,于是针对此进行优化。
优化方案一
在mybatis的xml文件中,使用foreach标签来拼接SQL语句。
代码示例:
<update id="updateBatchById"> <foreach collection="list" item="item" separator=";"> update `sys_dept` set `DEPT_NAME` = #{item.deptName}, `DEPT_CODE` = #{item.deptCode}, `PARENT_ID` = #{item.parentId} where dept_id = #{item.deptId} </foreach> </update>
mapper层:
void updateBatchById(@Param("list") List<SysDept> list);
然后在修改数据的逻辑中,直接调用mapper的接口
重启项目,再次测试:
可以看到,同样的数据,这个方案耗时273ms
优化方案二
foreach
标签配合case when
拼接SQL语句。
代码示例:
<update id="batchUpdate" parameterType="java.util.List"> update sys_dept <trim prefix="set" suffixOverrides=","> <trim prefix=" `DEPT_NAME` = case " suffix=" end, "> <foreach collection="list" item="item"> <if test="item.deptName != null"> when dept_id = #{item.deptId} then #{item.deptName} </if> </foreach> </trim> <trim prefix=" `DEPT_CODE` = case " suffix=" end, "> <foreach collection="list" item="item"> <if test="item.deptCode != null"> when dept_id = #{item.deptId} then #{item.deptCode} </if> </foreach> </trim> <trim prefix=" `PARENT_ID` = case " suffix=" end, "> <foreach collection="list" item="item"> <if test="item.parentId != null"> when dept_id = #{item.deptId} then #{item.parentId} </if> </foreach> </trim> </trim> where dept_id in <foreach collection="list" item="item" open="(" close=")" separator=","> #{item.deptId} </foreach> </update>
mapper层:
void batchUpdate(@Param("list") List<SysDept> list);
修改逻辑处直接调用:
重启项目,再次测试:
可以看到,同样的数据,这个方案耗时131ms。
经过多次测试会发现,在本案例中,优化方案二性能略强于优化方案一。
总结
使用mybatisplus的saveOrUpdateBatch操作效率极低,查看sql日志可以发现,实际上还是一条一条插入的,而且在插入之前还要查询数据库是否存在该数据,耗时很久,建议不要使用。优化方案一是多条sql语句,需要数据库执行多次修改操作,而优化方案二是一条sql语句,只需要数据库执行一次修改操作。在数据量不是特别大的情况下,优化方案二优于优化方案一。
在数据量不大的情况下,推荐使用方案二。
来源地址:https://blog.csdn.net/lianaozhe/article/details/129872757
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341