关于mybatis的批量更新

时间:2019-04-08 08:54:56

标签: java mysql jvm mybatis

我想批量更新数据,所以我使用两种方法。 第一,以“ 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时间。

0 个答案:

没有答案