文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

mysql批量插入性能优化:executeBatch如何通过rewriteBatchedStatements参数逆袭

2023-09-04 05:42

关注

文章目录


前言

前面关于mybatis-plus的文章中提到过内置的批量插入方法saveBatch并不是真正的批量写入,而是通过executeBatch分批提交。所以我们通过sql注入器注入InsertBatchSomeColumn方法实现了insert的多值插入,提升了批量插入的性能。但其实还有更简单的优化方式,只通过添加一个参数,就能让采用executeBatch批量插入数据的性能实现逆袭。

这就是今天给大家介绍的rewriteBatchedStatements参数。


一、实战演示

项目工程依然采用之前mybatis-plus系列文章中的工厂。
这里我们通过在不添加rewriteBatchedStatements参数的前后采用executeBatch批量执行插入1万数据,并与InsertBatchSomeColumn方法进行对比。

1、单元测试

    @Test    public void testBatchInsert() {        System.out.println("----- batch insert method test ------");        long startTime = System.currentTimeMillis();        List<User> list = new ArrayList<>();        for (int i = 0; i < 10000; i++) {            User user = new User();            user.setName("test");            user.setAge(13);            user.setEmail("101@qq.com");            list.add(user);        }        userService.saveBatch(list);        System.out.println("耗时:" + (System.currentTimeMillis() - startTime));    }

saveBatch方法默认情况下,每次提交1000条sql。
saveBatch方法的底层实现是通过executeBatch批量执行sql

default boolean saveBatch(Collection<T> entityList) {    return this.saveBatch(entityList, 1000);}public boolean saveBatch(Collection<T> entityList, int batchSize) {     String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);     return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {         sqlSession.insert(sqlStatement, entity);     }); }

2、不添加rewriteBatchedStatements参数

属性配置:

spring.datasource.url = jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=truespring.datasource.username = rootspring.datasource.password = 123456

测试结果:
在这里插入图片描述
说明是一条insert语句插入一条记录。
在这里插入图片描述
插入10000条数据,耗时49646ms

3、添加rewriteBatchedStatements参数

在mysql的数据库连接参数中添加rewriteBatchedStatements=true

spring.datasource.url = jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&rewriteBatchedStatements=truespring.datasource.username = rootspring.datasource.password = 123456

执行结果:
在这里插入图片描述
添加rewriteBatchedStatements=true后,executeBatch批量提交到mysql的sql语句还是一条insert语句插入一条记录
插入10000条数据耗时1289ms,批量插入的效率得到大幅提升。
在这里插入图片描述

4、采用InsertBatchSomeColumn方法

这里我们只需要将UserServiceImpl中采用InsertBatchSomeColumn重写的saveBatch方法的注释放开即可。

@Service@Slf4jpublic class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {    @Resource    private UserMapper userMapper;        @Override    @Transactional(rollbackFor = {Exception.class})    public boolean saveBatch(Collection<User> entityList, int batchSize) {        try {            int size = entityList.size();            int idxLimit = Math.min(batchSize, size);            int i = 1;            //保存单批提交的数据集合            List<User> oneBatchList = new ArrayList<>();            for(Iterator<User> var7 = entityList.iterator(); var7.hasNext(); ++i) {                User element = var7.next();                oneBatchList.add(element);                if (i == idxLimit) {                    userMapper.insertBatchSomeColumn(oneBatchList);                    //每次提交后需要清空集合数据                    oneBatchList.clear();                    idxLimit = Math.min(idxLimit + batchSize, size);                }            }        }catch (Exception e){            log.error("saveBatch fail",e);            return false;        }        return  true;    }}

执行单元测试:
可以看到,采用insertBatchSomeColumn方法进行的批量插入是采用了insert的多值插入,一条insert语句插入多条记录。这里每批插入1000条记录。
最终,插入10000条记录只话费了663ms

insertBatchSomeColumn方法由于底层并不是走的executeBatch批量提交sql,所以性能并不会受rewriteBatchedStatements参数的影响。
在这里插入图片描述在这里插入图片描述

二、官方文档

Mysql官方文档:rewriteBatchedStatements
在这里插入图片描述
核心:
prepared statements for INSERT into multi-value inserts when executeBatch() is called

rewriteBatchedStatements选项默认是关闭的,3.1.13以后的mysql连接驱动都支持该配置。
如果开启该配置rewriteBatchedStatements=true,在调用 executeBatch() 批量执行 INSERT语句时,mysql内部会自动将批量提交的sql重写为insert多值插入再执行。


总结

本文主要介绍在采用executeBatch进行mysql批量数据插入时,通过在mysql连接信息中添加rewriteBatchedStatements=true使得执行效率大幅提升。
1、批量sql重写开关参数rewriteBatchedStatements默认是关闭的,mysql连接驱动器版本3.1.13以后支持该配置。
2、其底层原理是:将通过executeBatch方法批量提交到mysql服务端的sql重写为insert多值插入再执行
3、通过测试发现,开启rewriteBatchedStatements后,采用executeBatch方法批量插入的性能已经接近InsertBatchSomeColumn真实insert多值批量写入。

来源地址:https://blog.csdn.net/w1014074794/article/details/125858863

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯