mybatis-plus优化-rewriteBatchedStatements飞速提升

mysql官方文档:rewriteBatchedStatements相关介绍

接下来我们用WWW的方式去了解rewriteBatchedStatements

一、是什么?

rewriteBatchedStatements 是Mysql 3.1.13版本新增的一个设置参数表示是否启用批量更新重写功能的配置参数,true代表开启,false代表关闭(默认)

网上很多文章说5.1.13以上版本的驱动(存疑),测试5.12版本也可以;过低版本会提示和springboot版本不兼容

二、为什么?

MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。

executeBatch():是一个 JDBC 方法,用于批量执行 SQL 语句。该方法可以一次性执行多个 SQL 语句,从而提高数据库操作的效率

只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL,另外这个选项对INSERT、UPDATE、DELETE都有效

三、怎么用?

将该参数添加到mysql的链接url

##配置链接mysql的时候将参数添加上并且将参数设置成true
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/learn_a?rewriteBatchedStatements=true&useSSL=false&serverTimezone=UTC&
    username: *******
    password: *******
    driver-class-name: com.mysql.cj.jdbc.Driver

四、影响

根据官网文档的示意,本地测试时没有发现update和delete的实际优化(各位看官老板发现可以私聊博主)

4.1 INSERT

我们对INSERT进行多场景分析,部分数据数据一致场景部分数据一致场景、数据完全不一致场景三种场景进行分析

4.1.1 场景一(数据一致)

SQL

--优化前
INSERT INTO users ( id, username, password, email ) VALUES ( 0, '张老0', '02103', '02103' )
INSERT INTO users ( id, username, password, email ) VALUES ( 0, '张老1', '12113', '12113' ) 
INSERT INTO users ( id, username, password, email ) VALUES ( 0, '张老2', '22123', '22123' )
--优化后
INSERT INTO users ( id, username, PASSWORD, email ) VALUES ( 0, '张老0', '02103', '02103' ),( 0, '张老1', '12113', '12113' ),( 0, '张老2', '22123', '22123' )

mysql日志输出

4.1.2 场景二(数据部分不一致)

场景2.1(1,2一致,3不一致)

SQL

--优化前
INSERT INTO users ( id, username, email ) VALUES ( 0, '张老0', '02103' )
INSERT INTO users ( id, username, email ) VALUES ( 0, '张老1', '12113' )
INSERT INTO users ( id, username, password, email ) VALUES ( 0, '张老2', '22123', '22123' )
--优化后(可以看到只有相邻的会进行合并优化)
INSERT INTO users (id, username, email) VALUES (0, '张老0', '02103'), (0, '张老1', '12113');
INSERT INTO users ( id, username, password, email ) VALUES ( 0, '张老2', '22123', '22123' )

mysql日志输出

场景2.2(1,3一致 2不一致)

SQL

--优化前
INSERT INTO users ( id, username, email ) VALUES ( 0, '张老0', '02103' )
INSERT INTO users ( id, username, password, email ) VALUES ( 0, '张老1', '12113', '12113' )
INSERT INTO users ( id, username, email ) VALUES ( 0, '张老2', '22123' )
--优化后(我们可以看到优化是和顺序是有关联的,所以这种极端的场景效率不会提升)
INSERT INTO users ( id, username, email ) VALUES ( 0, '张老0', '02103' )
INSERT INTO users ( id, username, password, email ) VALUES ( 0, '张老1', '12113', '12113' )
INSERT INTO users ( id, username, email ) VALUES ( 0, '张老2', '22123' )

mysql日志输出

4.1.3 场景三(数据全不一致)

SQL

--优化前  
INSERT INTO users ( id, username ) VALUES ( 0, '张老0' )
INSERT INTO users ( id, username, password ) VALUES ( 0, '张老1', '12113' )
INSERT INTO users ( id, username, email ) VALUES ( 0, '张老2', '22123' )
--优化后
INSERT INTO users ( id, username ) VALUES ( 0, '张老0' )
INSERT INTO users ( id, username, password ) VALUES ( 0, '张老1', '12113' )
INSERT INTO users ( id, username, email ) VALUES ( 0, '张老2', '22123' )

mysql日志输出

五、注意事项

  1. 数据库:表的设计必须存在默认值或者可以为NULL

  2. 使用saveBatch()批量插入会将sql整合为一条,需要注意合并后数据量过大引发的报错,具体大小可以查询数据库的max_allowed_packet

报错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.

查询max_allowed_packet命令:SELECT CONCAT( ROUND( (@@max_allowed_packet / (1024 * 1024)) ), ' MB' ) AS max_allowed_packet_mb;

规避方式:

  1. 调整max_allowed_packet的大小

  2. 写方法的时候根据插入数据量自己写个使用saveBatch(Collection<T> entityList, int batchSize)

六、结论

  1. 数据库:对数据表创建有要求,字段设置可以为空或存在默认值

  2. 驱动:对mysql驱动版本存在要求,要求5.1.13以上版本(测试5.1.12也是可以的)。

  3. 数据:当存储的无规则数据格式,无法进行优化效率很低。

  4. 根据上述验证过程sql优化存在顺序性,只有相邻的两条数据格式一致才会优化,并不会跨行优化。

  5. 经测试两条以上就会合并,网上部分文章说小于三条并不会优化存在出入。

想了解更多的请关注博主另一篇文章MyBatis 批量插入-优化&效率对比 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

常有理_

老板们赏点元子吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值