我想批量更新数据,所以我使用两种方法。 第一,以“ for”周期进行更新,并且一次完成所有事务。 第二,将mybatis的xml中的“ case-when” SQL连接在一起。 我认为第一种方法将是高效的,但是我的测试结论并不是,例如,当我更新5000个数据时,这些方法的效率是相同的,但是第二种方法使用了太多的jvm内存,特别是G1 Old Gen和G1生存空间,它无法及时回收。 我不知道为什么,请给我您的答案。
基于Springboot 2.0.6的项目,使用MySQL 5。
第一种方法,以“ for”周期更新。
@Transactional
public void testUpdate(){
User user;
long a = System.currentTimeMillis();
for(int i = 1; i < 5000; i++){
user = new User();
user.setId(i);
user.setUsername(RandomStringUtils.randomAlphanumeric(5));
user.setEmail(RandomStringUtils.randomAlphanumeric(5));
user.setPassword(RandomStringUtils.randomAlphanumeric(5));
user.setPhone(RandomStringUtils.randomAlphanumeric(5));
userMapper.updateByPrimaryKey(user);
}
long b = System.currentTimeMillis();
System.out.println("testUpdateT ************************ " + (b-a));
}
第二种方法,将mybatis的xml中的“ case-when” SQL结合在一起。
public void testUpdateBatch(){
User user;
long a = System.currentTimeMillis();
List<User> list = new ArrayList<>();
for(int i=1;i<5000;i++){
user = new User();
user.setId(i);
user.setUsername(RandomStringUtils.randomAlphanumeric(5));
user.setEmail(RandomStringUtils.randomAlphanumeric(5));
user.setPassword(RandomStringUtils.randomAlphanumeric(5));
user.setPhone(RandomStringUtils.randomAlphanumeric(5));
list.add(user);
}
userMapper.updateBatch(list);
long b = System.currentTimeMillis();
System.out.println("testUpdateT ************************ " + (b-a));
}
sql
<update id="updateBatch">
update user
<trim prefix="set" suffixOverrides=",">
<trim prefix="username =case" suffix="end,">
<foreach collection="list" item="i" index="index">
when id=#{i.id} then #{i.username}
</foreach>
</trim>
<trim prefix=" password =case" suffix="end,">
<foreach collection="list" item="i" index="index">
when id=#{i.id} then #{i.password}
</foreach>
</trim>
<trim prefix="email =case" suffix="end," >
<foreach collection="list" item="i" index="index">
when id=#{i.id} then #{i.email}
</foreach>
</trim>
<trim prefix="phone =case" suffix="end," >
<foreach collection="list" item="i" index="index">
when id=#{i.id} then #{i.phone}
</foreach>
</trim>
</trim>
where
<foreach collection="list" separator="or" item="i" index="index" >
id=#{i.id}
</foreach>
</update>
此表有27000个项目,第一个成本为5500ms,第二个成本为8000-10000ms,最重要的是,当第二个方法完成时,堆内存使用量会变大,并且在短时间内无法GC时间。