Мне нужны данные для пакетного обновления, поэтому я использую два метода.Во-первых, обновление в цикле «за» и все в одной транзакции.И, во-вторых, объединение 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 за короткий промежуток времени.