О пакетных обновлениях mybatis - PullRequest
1 голос
/ 08 апреля 2019

Мне нужны данные для пакетного обновления, поэтому я использую два метода.Во-первых, обновление в цикле «за» и все в одной транзакции.И, во-вторых, объединение SQL «case-when» в xml mybatis.Я думаю, что первый будет высокоэффективным, но мой вывод теста не такой, например, когда я обновляю 5000 данных, эффективность этих методов одинакова, но второй метод использует слишком много памяти jvm, в частности G1 Old Gen и G1Survivor Space, и он не может утилизироваться во времени.Я не знаю, почему это так, пожалуйста, дайте мне ваш ответ.

Проект основан на Springboot 2.0.6, используйте MySQL 5.

1-й метод, обновление в цикле '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));
    }

2-й метод, объединяющий SQL 'case-when' в xml mybatis.

        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 предметов, первый стоит 5500 мс, а второй стоит 8000-10000 мс, и самое важное, когда второй метод завершен, использование кучи памяти увеличивается, и он не может собрать GC за короткий промежуток времени.

...