对 MyBatis Plus SaveBatch 调优提升25倍性能!!!

其他系列文章导航

Java基础合集
数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、源码分析

二、优化过程

三、疑问

四、总结


前言

最近在压测一批接口,发现接口处理速度慢的有点超出预期,感觉很奇怪,后面定位发现是数据库批量保存这块很慢。

这个项目用的是 mybatis-plus,批量保存直接用的是 mybatis-plus 提供的 saveBatch。

于是开始排查之路。


一、源码分析

我点进去看了下源码,感觉有点不太对劲。

如下图所示:

图片

我继续追踪了下,从这个代码来看,确实是 for 循环一条一条执行了 sqlSession.insert,下面的 consumer 执行的就是上面的 sqlSession.insert。

如下图所示:

图片

然后累计一定数量后,一批 flush。

从这点来看,这个 saveBach 的性能肯定比直接一条一条 insert 快。

拼接 sql 的方式实现批量保存效率最佳。

但是我又不太甘心,总感觉应该有什么别的法子,然后我就继续跟着 mybatis-plus 的源码 debug 了一下,跟到了 mysql 的驱动,突然发现有个 if 里面的条件有点显眼。

如下图所示:

图片

就是这个叫 rewriteBatchedStatements 的玩意,从名字来看是要重写批操作的 Statement,前面batchHasPlainStatements 已经是 false,取反肯定是 true,所以只要这参数是 true 就会进行一波操作。

我看了下默认是 false。

如下图所示:

图片


二、优化过程

同时我也上网查了下 rewriteBatchedStatements 参数,好家伙,好像有用!

图片

我直接将 jdbcurl 加上了这个参数。

如下图所示:

图片

然后继续跑了下 mybatis-plus 自带的 saveBatch,果然性能大大提高,跟拼接 SQL 差不多!

如下图所示:

图片

顺带我也跑了下 JDBC 的 executeBatch ,果然也提高了。

如下图所示:

图片

然后我继续 debug ,来探探 rewriteBatchedStatements 究竟是怎么 rewrite 的!

如果这个参数是 true,则会执行下面的方法且直接返回。

如下图所示:

图片

看下 executeBatchedInserts 究竟干了什么?

如下图所示:

图片

看到上面我圈出来的代码没,好像已经有点感觉了,继续往下 debug。

果然!sql 语句被 rewrite了!!!

如下图所示:

图片

对插入而言,所谓的 rewrite 其实就是将一批插入拼接成 insert into xxx values (a),(b),(c)...这样一条语句的形式然后执行,这样一来跟拼接 sql 的效果是一样的。


三、疑问

那为什么默认不给这个参数设置为 true 呢?

我简单问了下 ChatGPT:

  1. 如果批量语句中的某些语句失败,则默认重写会导致所有语句都失败。

  2. 批量语句的某些语句参数不一样,则默认重写会使得查询缓存未命中。

看起来影响不大,所以我给我的项目设置上了这个参数!

稍微总结下我粗略的对比(虽然粗略,但实验结果符合原理层面的理解),如果你想更准确地实验,可以使用JMH,并且测试更多组数(如 5000,10000等)的情况。

批量保存方式数据量(条)耗时(ms)
单条循环插入1000121011
mybatis-plus saveBatch100059927
mybatis-plus saveBatch(添加rewtire参数)10002589
手动拼接sql10002275
jdbc executeBatch100055663
jdbc executeBatch(添加rewtire参数)1000324

四、总结

所以如果有使用 jdbc 的 Batch 性能方面的需求,要将 rewriteBatchedStatements 设置为 true,这样能提高很多性能。

然后如果喜欢手动拼接 sql 要注意一次拼接的数量,分批处理。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/220688.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件兼容性测试有哪些好处?专业CMA、CNAS软件测评中心推荐

软件兼容性测试是保证软件在不同操作系统、不同浏览器、不同设备上正常运行的重要环节。一款兼容性良好的软件能在不同的硬件和软件环境中展现出稳定、高效的性能,用户体验也会更加顺畅,主要有以下好处: 1、减少软件上线后的故障和问题&…

C //例10.1 从键盘输入一些字符,逐个把它们送到磁盘上去,直到用户输入一个“#”为止。

C程序设计 (第四版) 谭浩强 例10.1 例10.1 从键盘输入一些字符,逐个把它们送到磁盘上去,直到用户输入一个“#”为止。 IDE工具:VS2010 Note: 使用不同的IDE工具可能有部分差异。 代码块 方法:使用指针&…

Java-宋红康-(P133-P134)-多线程创建方式(Thread and Runnable)

b站视频 133-多线程-线程创建方式1:继承Thread类_哔哩哔哩_bilibili 目录 3.1 继承Thread 3.1.1 继承Thread类方式 3.1.2 线程的执行流程 3.1.3 线程内存图 3.1.4 run()方法和start()方法 3.1.5 线程名字的设置和获取 3.1.6 获取运行main方法线程的名字 3.…

【Java Web学习笔记】5 - XML

项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/xml 零、在线文档 XML系列教程 一、XML引出 1.为什么需要XML 1.需求1 :两个程序间进行数据通信? 2.需求2:给一台服务器,做-一个配置文件,当服务器程序启动时,去…

【AntDB 数据库】国产数据库发展之信创政策的加持

由于我国在信息技术领域起步较晚,国内大量的市场份额被国际IT巨头占据,甚至长期处于被垄断的地位,这也给了某些国家妄图通过挑起科技、贸易摩擦制衡我国发展的机会。为了解决可能存在的安全风险,在重要信息系统、关键基础设施中使…

linux-进程退出

进程终止 进程终止进程终止原因 进程返回值echo $?exit()和_exit() 父进程获取进程退出码wait()方法waitpid()方法获取子进程的退出码(status) 进程的非阻塞等待(WNOHANG)问题 进程终止 进程终止原因 进程终止原因有三种情况。 代码运行完毕&#xf…

【多线程】-- 12 线程协作之生产者消费者问题及解决办法

多线程 9 线程协作 “生产者消费者问题” ——并非二十三种设计模式之一 9.1 生产者消费者问题 “线程通信” 应用场景:生产者和消费者问题 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费如果…

linux 服务的JDK安装

1.jdk安装 1.1 jdk下载 官网下载地址:https://www.oracle.com/java/technologies/downloads/ 这里我使用的是rpm的方式,所以下载rpm的包。如下图:1.2 jdk的安装 下载完成后,会有一个以rpm结尾的包,例如:jd…

【恋上数据结构】哈夫曼树学习笔记

哈夫曼树 哈夫曼编码(Huffman Coding) 哈夫曼编码,又称为霍夫曼编码,它是现代压缩算法的基础 假设要把字符串 [ABBBCCCCCCCCDDDDDDEE] 转成二进制编码进行传输。 可以转成 ASCII 编码 (6569,10000011000101) &…

牛客算法题【HJ96 表示数字】golang实现

题目 HJ96 表示数字 golang实现 package mainimport ("fmt""unicode" )func main() {s : ""var s_o stringvar char_pre, r runefor {n, _ : fmt.Scan(&s)if n 0 {break} else {for _, r range s {if unicode.IsDigit(r) {if !unicode.…

前端模拟新闻列表ajax请求 mocky

效果图&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title> </head><style>ul {display: flex;flex-wrap: wrap;justify-content: space-between;}ul::after{content: ;width: 30%;}a…

L1-004:计算摄氏温度

题目描述 给定一个华氏温度F&#xff0c;本题要求编写程序&#xff0c;计算对应的摄氏温度C。计算公式&#xff1a;C5(F−32)/9。题目保证输入与输出均在整型范围内。 输入格式&#xff1a;输入在一行中给出一个华氏温度。 输出格式&#xff1a;在一行中按照格式“Celsius C”…

创建vue3数学符号选择器(vue3+elementPlus+ts)

本文包含两种效果&#xff1a; 效果一&#xff1a;数学符号只能选择一次&#xff0c;选中的数学符号高亮 效果二&#xff1a;相同的数学符号可以选择多次&#xff0c;当前选中的数学符号高亮 首先创建math.ts定义常见数学符号数组 : export const symbols [{ id: 1, value: …

数据结构与算法-D2D3线性表之顺序表

线性表&#xff1a;包含若干数据元素的一个线性序列&#xff0c;特征如下&#xff1a; 1&#xff09;对非空表&#xff0c;a0是表头&#xff0c;无前驱&#xff1b; 2&#xff09;an-1是表尾&#xff0c;无后继&#xff1b; 3&#xff09;其他元素仅且仅有一个前驱&#xff0c;…

CSS面经(未完待续)

1. CSS选择器及其优先级 !important > 行内样式 > id选择器 > 类/伪类/属性选择器 > 标签/伪元素选择器 > 子/后台选择器 > *通配符 2. 重排和重绘是什么&#xff1f;浏览器的渲染机制是什么&#xff1f; 重排(回流)&#xff1a;当增加或删除dom节点&…

Centos7上安装Redis

第一步&#xff1a;安装Redis依赖 yum install -y gcc tcl //需要使用管理员权限第二步&#xff1a;下载上传安装包并解压 下载地址redis中文官网 上传成功后解压 输入tar -zxvf &#xff08;redis版本&#xff09;,即可解压成功 进入redis目录&#xff0c;运行编译命令&am…

人工智能学习3(特征变换:特征数值化)

编译工具&#xff1a;PyCharm 有些编译工具不用写print可以直接将数据打印出来&#xff0c;pycharm需要写print才会打印出来。 文章目录 编译工具&#xff1a;PyCharm 概念1.特征类型分类型二值型顺序型数值型 2.特征数值化练习13.特征数值化练习24.特征二值化使用sklearn库自…

信号是怎么搞到电磁波上面去的呢?

在之前的文章中&#xff0c;我们曾多次讲到电磁波的美妙&#xff0c;但是有了电磁波就可以通信了吗&#xff1f; No&#xff0c;我们要把信息加载到电磁波上&#xff0c;这个电磁波就可以作为信息的载体来工作了。可是信号是怎么加载到电磁波上的呢&#xff1f; 今天我们一起…

Javafx实现浏览器

浏览器是一种计算机程序&#xff0c;主要用于显示互联网上的网页。通过浏览器&#xff0c;用户可以访问各种网站、搜索引擎、在线应用程序、社交媒体等。常见的浏览器包括Google Chrome、Mozilla Firefox、Safari、Microsoft Edge、Opera等。浏览器的功能不仅限于浏览网页&…

无线网卡填坑记

没想到我安装无线网卡这么波澜起伏~ 起因 近来刚在电脑上玩完了 Dishonored 2&#xff0c;紧接着继续着我的刺客信条之旅。总是觉得键盘鼠标玩起来不爽&#xff0c;还是手柄玩这种游戏才舒服。突然&#xff0c;灵光一现&#xff0c;我想到正好有闲置的 Switch 掌机没怎么玩&am…