当前位置:   article > 正文

mysql批量更新方式的比较_replace和update谁快

replace和update谁快

前言

在使用Mysql进行批量更新的时候,总会想哪一种方式效率更高,于是干脆进行了测试。

先说结论:

常见的四种方式有

  1. 直接一条记录一个update
  2. 使用case when
  3. 使用replace into
  4. 使用insert update duplicate on

1w条记录分10次插入时,每种方式平均用时如下(编号对应上面的记录,单位是毫秒):

1:21392

2:318

3:221

4:241

每次插入1w条,重复插入10次,每种方式评价用时如下(方式1直接淘汰不测了):

2:7678

3:919

4:804

所以,replace into 和update duplicate胜出

详细数据

1k条记录重复10次

case when

第0次,花费:1357 第1次,花费:191 第2次,花费:175 第3次,花费:230 第4次,花费:566 第5次,花费:142 第6次,花费:117 第7次,花费:122 第8次,花费:145 第9次,花费:135 平均花费:318

分析认为有可能是插入的是重复的id,有缓存加速的原因,后面几次很快,需要再测1w条记录分10次的情况分析,后者更实际

multiple

即单纯的一次多条update,需要在jdbc的url上加allowMultiQueries=true参数

速度巨慢,不参与1w条的测试

第0次,花费:23846 第1次,花费:23442 第2次,花费:22097 第3次,花费:19793 第4次,花费:19351 第5次,花费:20448 第6次,花费:22631 第7次,花费:19940 第8次,花费:19598 第9次,花费:22783 平均花费:21392

replace into

第0次,花费:1131 第1次,花费:96 第2次,花费:81 第3次,花费:77 第4次,花费:73 第5次,花费:308 第6次,花费:208 第7次,花费:86 第8次,花费:80 第9次,花费:78 平均花费:221

效率相当可观但是颇为危险,诸如有多个主键或主从表的情况容易造成错误

insert duplicate

Mybatis 通过DUPLICATE实现在INSERT中批量高效更新数据_BasicLab基础架构实验室的博客-CSDN博客_mybatis duplicate

上面这篇博客相当不错

第0次,花费:1278 第1次,花费:174 第2次,花费:339 第3次,花费:98 第4次,花费:100 第5次,花费:83 第6次,花费:86 第7次,花费:80 第8次,花费:86 第9次,花费:87 平均花费:241

与replace相差无几

replace与duplicate都非常容易改变主键,而且是不可逆的改变,使用当慎重

1w条数据分10次

case when

第0次,花费:1330 第1次,花费:189 第2次,花费:199 第3次,花费:184 第4次,花费:236 第5次,花费:258 第6次,花费:169 第7次,花费:159 第8次,花费:209 第9次,花费:198 平均花费:313

变化不大,大概是有自适应索引等原因,速度依然不错

replace into

第0次,花费:1133 第1次,花费:108 第2次,花费:103 第3次,花费:96 第4次,花费:104 第5次,花费:70 第6次,花费:63 第7次,花费:94 第8次,花费:100 第9次,花费:217 平均花费:208

变化不大

insert duplicate

第0次,花费:1141 第1次,花费:137 第2次,花费:88 第3次,花费:77 第4次,花费:87 第5次,花费:96 第6次,花费:86 第7次,花费:114 第8次,花费:117 第9次,花费:181 平均花费:212

1w条数据重复10次

case when

第0次,花费:10300 第1次,花费:8184 第2次,花费:7537 第3次,花费:7256 第4次,花费:7336 第5次,花费:7260 第6次,花费:7145 第7次,花费:7249 第8次,花费:7276 第9次,花费:7242 平均花费:7678

replace into

第0次,花费:2140 第1次,花费:2007 第2次,花费:735 第3次,花费:560 第4次,花费:616 第5次,花费:594 第6次,花费:605 第7次,花费:722 第8次,花费:633 第9次,花费:587 平均花费:919

insert duplicate

第0次,花费:1845 第1次,花费:808 第2次,花费:1652 第3次,花费:521 第4次,花费:604 第5次,花费:482 第6次,花费:534 第7次,花费:603 第8次,花费:481 第9次,花费:514 平均花费:804

测试实例

下面列出本人测试时的代码与环境

mysql 8.0+

表结构

  1. DROP TABLE IF EXISTS `updatetest`;
  2. CREATE TABLE `updatetest` (
  3. `id` bigint(0) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
  4. `col1` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  5. `col2` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  6. `col3` int(0) UNSIGNED NOT NULL,
  7. `col4` int(0) UNSIGNED NOT NULL,
  8. `col5` char(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  9. `gmt_create` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  10. `gmt_modified` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0),
  11. PRIMARY KEY (`id`) USING BTREE
  12. ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = REDUNDANT STORAGE MEMORY;
  13. SET FOREIGN_KEY_CHECKS = 1;

mapper类

  1. @Mapper
  2. public interface UpdateMapper {
  3. void updateByMultiple(@Param("list") List<UpdatetestDO> list);
  4. void updateByCase(@Param("list") List<UpdatetestDO> list);
  5. void updateByReplace(@Param("list") List<UpdatetestDO> list);
  6. void updateByDuplicate(@Param("list") List<UpdatetestDO> list);
  7. void initInsert(@Param("list") List<UpdatetestDO> list);
  8. }

 xml文件

  1. <insert id="initInsert">
  2. insert into
  3. updatetest(col1, col2, col3, col4, col5)
  4. values
  5. <foreach collection="list" item="it" separator=",">
  6. (#{it.col1},#{it.col2},#{it.col3},#{it.col4},#{it.col5})
  7. </foreach>
  8. </insert>
  9. <update id="updateByMultiple">
  10. <foreach collection="list" item="it">
  11. update
  12. updatetest
  13. set
  14. col1=#{it.col1},
  15. col2=#{it.col2},
  16. col3=#{it.col3},
  17. col4=#{it.col4},
  18. col5=#{it.col5}
  19. where id=#{it.id};
  20. </foreach>
  21. </update>
  22. <update id="updateByCase">
  23. update
  24. updatetest
  25. <trim prefix="set" suffixOverrides=",">
  26. <foreach collection="list" item="it" open="col1 = case id" close="end,">
  27. when #{it.id} then #{it.col1}
  28. </foreach>
  29. <foreach collection="list" item="it" open="col2 = case id" close="end,">
  30. when #{it.id} then #{it.col2}
  31. </foreach>
  32. <foreach collection="list" item="it" open="col3 = case id" close="end,">
  33. when #{it.id} then #{it.col3}
  34. </foreach>
  35. <foreach collection="list" item="it" open="col4 = case id" close="end,">
  36. when #{it.id} then #{it.col4}
  37. </foreach>
  38. <foreach collection="list" item="it" open="col5 = case id" close="end,">
  39. when #{it.id} then #{it.col5}
  40. </foreach>
  41. </trim>
  42. WHERE id IN
  43. (<foreach collection="list" item="it" separator=",">
  44. #{it.id}
  45. </foreach>)
  46. </update>
  47. <insert id="updateByReplace">
  48. replace into
  49. updatetest(id,col1, col2, col3, col4, col5)
  50. values
  51. <foreach collection="list" item="it" separator=",">
  52. (#{it.id},#{it.col1},#{it.col2},#{it.col3},#{it.col4},#{it.col5})
  53. </foreach>
  54. </insert>
  55. <insert id="updateByDuplicate">
  56. insert into
  57. updatetest(id,col1, col2, col3, col4, col5)
  58. values
  59. <foreach collection="list" item="it" separator=",">
  60. (#{it.id},#{it.col1},#{it.col2},#{it.col3},#{it.col4},#{it.col5})
  61. </foreach>
  62. on duplicate key update
  63. col1=values(col1),
  64. col2=values(col2),
  65. col3=values(col3),
  66. col4=values(col4),
  67. col5=values(col5)
  68. </insert>

测试类

  1. @SpringBootTest
  2. @RunWith(SpringJUnit4ClassRunner.class)
  3. public class FrameApplicationTests {
  4. @Autowired
  5. UpdateMapper mapper;
  6. @Test
  7. public void initInsert() {
  8. ArrayList<UpdatetestDO> dos = new ArrayList<>();
  9. for (long i = 1001L; i <= 10000L; i++) {
  10. UpdatetestDO it = new UpdatetestDO("col1" + i, "col2" + i, i, i, "col5" + i);
  11. dos.add(it);
  12. }
  13. mapper.initInsert(dos);
  14. }
  15. @Test
  16. public void caseTest(){
  17. long all=0;
  18. for (int cnt = 0; cnt < 10; cnt++) {
  19. ArrayList<UpdatetestDO> dos = new ArrayList<>();
  20. for (long i = 1L; i <= 10000L; i++) {
  21. UpdatetestDO it = new UpdatetestDO("col1:"+cnt+":" + i, "col2:case:" + i, i, i, "col5:cnt:" + i);
  22. it.setId(i);
  23. dos.add(it);
  24. }
  25. long start = System.currentTimeMillis();
  26. mapper.updateByCase(dos);
  27. long end = System.currentTimeMillis();
  28. long spend=end-start;
  29. System.out.println("第"+cnt+"次,花费:"+spend);
  30. all+=spend;
  31. }
  32. System.out.println("平均花费:"+all/10);
  33. }
  34. @Test
  35. public void multipleTest(){
  36. long all=0;
  37. for (int cnt = 0; cnt < 10; cnt++) {
  38. int base=cnt*1000;
  39. ArrayList<UpdatetestDO> dos = new ArrayList<>();
  40. for (long i = 1L; i <= 1000L; i++) {
  41. UpdatetestDO it = new UpdatetestDO("col1:"+base+":" + i, "col2:mul" + i, i, i, "col5:cnt:" + i);
  42. it.setId(base+i);
  43. dos.add(it);
  44. }
  45. long start = System.currentTimeMillis();
  46. mapper.updateByMultiple(dos);
  47. long end = System.currentTimeMillis();
  48. long spend=end-start;
  49. System.out.println("第"+cnt+"次,花费:"+spend);
  50. all+=spend;
  51. }
  52. System.out.println("平均花费:"+all/10);
  53. }
  54. @Test
  55. public void replaceTest(){
  56. long all=0;
  57. for (int cnt = 0; cnt < 10; cnt++) {
  58. ArrayList<UpdatetestDO> dos = new ArrayList<>();
  59. for (long i = 1L; i <= 10000L; i++) {
  60. UpdatetestDO it = new UpdatetestDO("col1:"+cnt+":" + i, "col2:rep:" + i, i, i, "col5:cnt:" + i);
  61. it.setId(i);
  62. dos.add(it);
  63. }
  64. long start = System.currentTimeMillis();
  65. mapper.updateByReplace(dos);
  66. long end = System.currentTimeMillis();
  67. long spend=end-start;
  68. System.out.println("第"+cnt+"次,花费:"+spend);
  69. all+=spend;
  70. }
  71. System.out.println("平均花费:"+all/10);
  72. }
  73. @Test
  74. public void duplicateTest(){
  75. long all=0;
  76. for (int cnt = 0; cnt < 10; cnt++) {
  77. ArrayList<UpdatetestDO> dos = new ArrayList<>();
  78. for (long i = 1L; i <= 10000L; i++) {
  79. UpdatetestDO it = new UpdatetestDO("col1:"+cnt+":" + i, "col2:dup:" + i, i, i, "col5:cnt:" + i);
  80. it.setId(i);
  81. dos.add(it);
  82. }
  83. long start = System.currentTimeMillis();
  84. mapper.updateByDuplicate(dos);
  85. long end = System.currentTimeMillis();
  86. long spend=end-start;
  87. System.out.println("第"+cnt+"次,花费:"+spend);
  88. all+=spend;
  89. }
  90. System.out.println("平均花费:"+all/10);
  91. }
  92. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/404855?site
推荐阅读
相关标签
  

闽ICP备14008679号