今天我们围绕Mybatis批量插入的三种方式的效率&优劣进行详解
一、Mybatis批量插入的三种方式
- for循环单次插入方式
- 批量插入(**伪批量**)
- 批量插入(**真批量**插入-两种实现方式)
二、三种方式的具体实现
-
for循环单次插入(不多进行赘述);
-
批量插入功能(伪批量插入):mybatisplus-伪批量插入saveBatch
-
批量插入(真批量插入)
-
重写方法(通用性强-仅限MYSQL):Mybatis真实批量插入-重写方法 InsertBatchSomeColumn
-
修改配置(代码侵入性低):mybatis-plus优化-rewriteBatchedStatements飞速提升
-
三、三种方式的效率对比
为了避免偶然性,我们会分别测试10、100、1000、10000条为数据样本的宽表和窄表两组数据;
每组数据又分为规则数据和不规则数据,规则数据为全字段有值的数据,不规则数据为随机字段有值
此处窄表为5个字段的数据表,宽表为30个字段的数据表。
3.1 窄表样本
3.1.1规则数据-测试结果
规则数据 | 10条 | 100条 | 1000条 | 10000条 |
for循环插入 | 31 | 179 | 1919 | 19572 |
批量插入(伪批量) | 25 | 134 | 1367 | 14455 |
批量插入(真实.配置) | 12 | 29 | 68 | 640 |
批量插入(真批量.方法.1000) | 7 | 10 | 62 | 852 |
表3.1 窄表-规则数据测试耗时 (ms)
图3.1 窄表-规则数据耗时 (ms)
3.1.2不规则数据-测试结果
无规则数据字段 | 10条 | 100条 | 1000条 | 10000条 |
for循环插入 | 26 | 189 | 2804 | 38121 |
批量插入(伪批量) | 24 | 192 | 1814 | 18379 |
批量插入(真实.配置) | 25 | 299 | 2217 | 24650 |
批量插入(真批量.方法.1000) | 4 | 22 | 59 | 652 |
表3.2 窄表-不规则数据测试耗时 (ms)
图3.2 窄表-不规则数据耗时 (ms)
3.2 宽表样本
3.2.1 规则数据-测试结果
规则数据 | 10条 | 100条 | 1000条 | 10000条 |
for循环插入 | 113 | 377 | 4541 | 33638 |
批量插入(伪批量) | 44 | 222 | 1859 | 18685 |
批量插入(真实.配置) | 12 | 36 | 247 | 3764 |
批量插入(真批量.方法.1000) | 14 | 60 | 558 | 7632 |
表3.3 宽表-规则数据测试耗时 (ms)
图3.3 宽表-规则数据耗时 (ms)
3.2.2 不规则数据-测试结果
无规则数据字段 | 10条 | 100条 | 1000条 | 10000条 |
for循环插入 | 55 | 341 | 2384 | 23959 |
批量插入(伪批量) | 25 | 209 | 1891 | 18768 |
批量插入(真实.配置) | 40 | 301 | 2215 | 21123 |
批量插入(真批量.方法.1000) | 9 | 68 | 507 | 5847 |
表3.4 宽表-不规则数据测试耗时 (ms)
图3.4 宽表-不规则数据耗时 (ms)
四、结论
各种批量插入方式的效率
规则数据场景:真批量.配置 > 真批量.方法 > 伪批量 > for
全无规则数据场景:真批量.方法 > 伪批量 > 真批量.配置 >for
下图为各种数据场景下四种方式插入10000条数据的耗时
-
for强烈不建议使用,批量数据插入的时候效率过低。
-
伪批量存储(一般推荐)
-
优点:可以根据bean的字段自行调整每次存储的sql,mybatis现有无需任何配置
-
缺点:效率还是低于批量存储
-
-
批量存储(推荐):
前提条件:数据库字段设置为null,或者 not null 但是需要给默认值,否则不支持
-
配置方式:
-
优点:
-
改动小,代码的侵入性低,仅需添加一行配置
-
效率高于mybatis-plus自带的批量插入方式,极大提高效率
-
-
缺点:
-
数据库:对数据表创建有要求,字段设置可以为空或存在默认值
-
驱动:对mysql驱动版本存在要求,要求5.1.13以上版本(测试5.1.12也是可以的)
-
数据:当存储的数据不规则的场景,无法进行优化效率很低
-
-
-
新增方法:
-
优点:效率极高,对存储的数据格式没有任何限制
-
缺点:
-
方法:需要新增方法新建对应的批量插入的方式,改动相对配置较多
-
数据库:对数据表创建有要求,字段设置可以为空或存在默认值
-
提交:默认是全量提交,但是会产生问题数据量过大超出mysql传输限制,就需要我们进行切割,并不是每次切割数量越大越好,过长会影响mysql内部编译效率
-
-
-
注意:如果不进行切割,单次提交过多会导致: Packet for query is too large (5,509,325 > 4,194,304). You can change this value on the server by setting the 'max_allowed_packet' variable.
查询方法:select @@max_allowed_packet/(1024*1024);
感谢各位看官老爷的耐心阅读,如有问题及时交流!