Jdbc批处理功能和MybatisPlus
文章目录
- 1. 序言
- 2. JDBC批处理功能和rewriteBatchedStatements
- 3. JDBC批量插入的测试
- 4. MybatisPlus#ServiceImpl.saveBatch()
- 5. 结语:如果对大家有帮助,请点赞支持。如果有问题随时在评论中指出,感谢。
1. 序言
MybatisPlus的ServiceImpl类中提供了批处理方法saveBatch,用来批量插入数据,速度要比”一个一个”插入更快。而这个方法的底层依赖了JDBC数据库驱动的批处理功能。
本文先介绍JDBC数据库驱动的批处理功能,然后对"JDBC批量插入"进行性能测试,从而说明saveBatch快的原因,最后说明MybatisPlus ServiceImpl.saveBatch的最佳使用方式(其实就一句话)。
2. JDBC批处理功能和rewriteBatchedStatements
- JDBC批处理功能是指:将多条SQL语句打包起来,一次性发给数据库服务器,服务器执行后将结果返回给客户端。相对于单条SQL逐条发送,批处理功能可以减少网络传输开销。JDBC的Statement和PreparedStatement都支持批处理,下面测试基于PreparedStatement。
- PreparedStatement.addBatch()用来添加一条SQL到列表中,但是不会提交给服务器。
- PreparedStatement.executeBatch()将列表中的所有SQL提交给服务器,并获得执行结果。
- rewriteBatchedStatements:假如数据库URL连接设置了参数rewriteBatchedStatements=true,那么执行executeBatch()时,多条INSERT语句就会被重写为一条INSERT语句,再发送给服务器,使得插入速度更快。默认值为false。
3. JDBC批量插入的测试
- 配置:MySQL驱动 8.3.0,两台电脑:PC1运行MySQL服务器,PC2作为客户端运行以下测试程序,PC1和PC2在同一局域网。
- 表结构:
CREATE TABLE `user` (`id` bigint NOT NULL,`username` varchar(255) NOT NULL,`age` int NOT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
- 获取数据库连接代码
private Connection getConnection() throws Exception {String url = "jdbc:mysql://192.168.1.9:3306/jdbc";String username = "root";String password = "root";return DriverManager.getConnection(url, username, password);}
- 逐条插入:耗时171172 ms
@Testpublic void testSingleInsert() throws Exception {long start = System.currentTimeMillis();// 逐条SQL语句发送Connection conn = getConnection();PreparedStatement psmt = conn.prepareStatement("INSERT INTO user VALUES (?, ?, ?)");for (int i=1; i<=10000; i++) {psmt.setLong(1, i);psmt.setString(2, "user_" + i);psmt.setInt(3, 17);psmt.execute();}long end = System.currentTimeMillis();
// 171172 msSystem.out.println("cost = " + (end-start) + " ms");}
- 批量插入:耗时116244 ms,使用批处理减少了网络开销,变快了。
@Testpublic void testBatchInsert() throws Exception {long start = System.currentTimeMillis();// 批量SQL发送Connection conn = getConnection();PreparedStatement psmt = conn.prepareStatement("INSERT INTO user VALUES (?, ?, ?)");for (int i=1; i<=10000; i++) {psmt.setLong(1, i);psmt.setString(2, "user_" + i);psmt.setInt(3, 17);psmt.addBatch();if (i % 1000 == 0) {psmt.executeBatch();}}long end = System.currentTimeMillis();
// 116244 msSystem.out.println("cost = " + (end-start) + " ms");}
注意:经过测试,如果MySQL服务器和客户端运行在同一台PC,"批量插入"和上一个"逐条插入"花费时间差不多,因为网络传输消耗的时间太小。
- 批量插入 + 手动开启事务:耗时68922 ms
上一个"批量插入"的例子,服务器执行每一条INSERT SQL都会自动开启和提交事务。而"批量插入 + 手动开启事务"只开启和提交了一次事务,所以速度会更快。
@Testpublic void testBatchInsertWithTransaction() throws Exception {long start = System.currentTimeMillis();// 批量SQL发送Connection conn = getConnection();conn.setAutoCommit(false);PreparedStatement psmt = conn.prepareStatement("INSERT INTO user VALUES (?, ?, ?)");for (int i=1; i<=10000; i++) {psmt.setLong(1, i);psmt.setString(2, "user_" + i);psmt.setInt(3, 17);psmt.addBatch();if (i % 1000 == 0) {psmt.executeBatch();}}conn.commit();long end = System.currentTimeMillis();//cost = 68922 msSystem.out.println("cost = " + (end-start) + " ms");}
- 批量插入 + 手动开启事务 + rewriteBatchedStatements:耗时1532 ms
private Connection getConnection() throws Exception {// 添加参数rewriteBatchedStatements=trueString url = "jdbc:mysql://192.168.1.9:3306/jdbc?rewriteBatchedStatements=true";String username = "root";String password = "root";return DriverManager.getConnection(url, username, password);}@Testpublic void testBatchInsertWithTransactionAndRewrite() throws Exception {long start = System.currentTimeMillis();// 批量SQL发送,Connection conn = getConnection();conn.setAutoCommit(false);PreparedStatement psmt = conn.prepareStatement("INSERT INTO user VALUES (?, ?, ?)");for (int i=1; i<=10000; i++) {psmt.setLong(1, i);psmt.setString(2, "user_" + i);psmt.setInt(3, 17);psmt.addBatch();if (i % 1000 == 0) {psmt.executeBatch();}}conn.commit();long end = System.currentTimeMillis();//cost = 1532 msSystem.out.println("cost = " + (end-start) + " ms");}
可见"批量插入 + 手动开启事务 + rewriteBatchedStatements"速度最快。
4. MybatisPlus#ServiceImpl.saveBatch()
MybatisPlus 3.5.8

可以看到ServiceImpl.saveBatch是开启了事务的,因此性能 = “批量插入 + 手动开启事务”。
所以通常我们会在JDBC数据库连接的后面加上rewriteBatchedStatements=true,变成"批量插入 + 手动开启事务 + rewriteBatchedStatements",达到最佳性能。
因此MybatisPlus批量插入的最佳方式是:saveBatch + rewriteBatchedStatements。
5. 结语:如果对大家有帮助,请点赞支持。如果有问题随时在评论中指出,感谢。
相关文章:
Jdbc批处理功能和MybatisPlus
文章目录 1. 序言2. JDBC批处理功能和rewriteBatchedStatements3. JDBC批量插入的测试4. MybatisPlus#ServiceImpl.saveBatch()5. 结语:如果对大家有帮助,请点赞支持。如果有问题随时在评论中指出,感谢。 1. 序言 MybatisPlus的ServiceImpl类…...
对于相对速度的重新理解
狭义相对论速度合成公式如下, 现在让我们尝试用另一种方式把它推导出来。 我们先看速度的定义, 常规的速度合成方式如下, 如果我们用速度的倒数来理解速度, 原来的两个相对速度合成, 是因为假定了时间单位是一样的&am…...
Scala的属性访问权限(一)默认访问权限
//eg:银行账户存钱取钱 // 账户类: // -balance() 余额 // -deposit() 存钱 // -withdraw() 取钱 // -transfer(to:账户,amount:Dobule)转账 package Test1104 //银行账户class BankAccount(private var balance:Int){def showMoney():Unit {println(s"…...
【算法】(Python)贪心算法
贪心算法: 又称贪婪算法,greedy algorithm。贪心地追求局部最优解,即每一步当前状态下最优选择。试图通过各局部最优解达到最终全局最优解。但不从整体最优上考虑,不一定全局最优解。步骤:从初始状态拆分成一步一步的…...
条件logistic回归原理及案例分析
前面介绍的二元、多分类、有序Logistic回归都属于非条件Logistic回归,每个个案均是相互独立关系。在实际研究中,还有另外一种情况,即个案间存在配对关系,比如医学研究中配对设计的病例对照研究,此时违反了个案相互独立…...
redis7学习笔记
文章目录 1. 简介1.1 功能介绍1.1.1 分布式缓存1.1.2 内存存储和持久化(RDBAOF)1.1.3 高可用架构搭配1.1.4 缓存穿透、击穿、雪崩1.1.5 分布式锁1.1.6 队列 1.2 数据类型StringListHashSetZSetGEOHyperLogLogBitmapBitfieldStream 2. 命令2.1 通用命令copydeldumpexistsexpire …...
重学Android:自定义View基础(一)
前言 作为一名安卓开发,也被称为大前端,做一个美观的界面,是我们必备的基础技能,可能在开发中我们最常用的是系统自带的View,因为他能满足绝大部分需求,难一点的我们也可以上Github上找个三方库使用&#…...
前端好用的网站分享——CSS(持续更新中)
1.CSS Scan 点击进入CSS Scan CSS盒子阴影大全 2.渐变背景 点击进入color.oulu 3.CSS简化压缩 点击进入toptal 4.CSS可视化 点击进入CSS可视化 这个强推,话不多说,看图! 5.Marko 点击进入Marko 有很多按钮样式 6.getwaves 点击进入getwaves 生…...
华为HarmonyOS借助AR引擎帮助应用实现虚拟与现实交互的能力3-获取设备位姿
设备位姿描述了物体在真实世界中的位置和朝向。AR Engine提供了世界坐标下6自由度(6DoF)的位姿计算,包括物体的位置(沿x、y、z轴方向位移)和朝向(绕x、y、z轴旋转)。通过AR Engine,您…...
qt QColorDialog详解
1、概述 QColorDialog是Qt框架中的一个对话框类,专门用于让用户选择颜色。它提供了一个标准的颜色选择界面,其中包括基本的颜色选择器(如调色板和颜色轮)、自定义颜色输入区域以及预定义颜色列表。QColorDialog支持RGB、HSV和十六…...
【测试小白--如何写好测试用例--测试用例编写的方法+结合常见登录模块为实例--保姆级教学】
测试用例编写方法&登录模块实例 一、测试用例编写方法1. 等价类划分2. 边界值分析3. 状态转换测试4. 决策表测试5. 错误推测6. 用户场景测试7. 安全测试用例 二、登录模块测试用例实例1. 等价类划分2. 边界值分析3. 状态转换测试4. 决策表测试5. 错误推测6. 用户场景测试7.…...
真题--数组循环题目
1.逆序数表达数组2.用数组表示费波纳希数列3.用数组排序4.二维数组转置5.找到二维数组其中的最大数值6.输出字符数组7.字符数组输出菱形图案8.输入一行字符,统计有多少单词9.有三个字符串,找到最大字符串 1.逆序数表达数组 #include<stdio.h> int…...
【Linux系列】在Linux下安装微信
文章目录 前言一、通用Linux系统使用Flatpak安装(推荐)1. 安装flatpak2. 安装微信 二、国产Linux 前言 此前,微信的Linux版一直在内测阶段,只有在国产的Linux系统和Debian系系统上可以正常安装,如果有心细的好伙伴应该…...
还在使用ElementUI不如试一试DaisyUI,DaisyUI: Tailwind CSS 的高效组件库,
DaisyUI: Tailwind CSS 的高效组件库 daisyUI官网:https://daisyui.com/ 在现代网页开发中,快速构建美观且响应式的用户界面是每个开发者追求的目标。Tailwind CSS 是一个流行的实用程序优先的 CSS 框架,它允许开发者直接在 HTML 中使用预…...
高光谱激光雷达遥感团队成员白杰博士获全国激光雷达优博论文奖
\quad \quad 2024年11月1日—4日,第八届全国激光雷达大会在桂林理工大学大学召开。本届大会,国际数字地球学会中国国家委员会激光雷达专业委员会组织了本年度优秀博士学位论文评选,经初评、函评、投票和公示,最终评选出了全国激光…...
24年配置CUDA12.4,Pytorch2.5.1,CUDAnn9.5运行环境
没什么好介绍的,直接说了。 下载 首先打开命令行,输入代码查看显卡最高支持的cuda版本,下载的版本不要高于该版本 nvidia-smi PyTorch 插件这个是PyTorch下载地址,就按照我这么选CUDA版本就选最新的,看好绿框里的CU…...
基于springboot得高校评教教师工作量管理系统设计与实现
项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…...
Rust 力扣 - 1456. 定长子串中元音的最大数目
文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们遍历长度为k的窗口,我们只需要记录窗口内的元音字母数量即可,遍历过程中刷新最大数目 题解代码 impl Solution {pub fn max_vowels(s: String, k: i32) -> i32 {let s s.as_byt…...
【Golang】validator库的使用
package mainimport ("fmt""github.com/go-playground/validator" )// MyStruct .. validate:"is-awesome"是一个结构体标签,它告诉验证器使用名为is-awesome的验证规则来验证String字段。 type MyStruct struct {String string vali…...
【AI日记】24.11.06 我对投资的一点浅见
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 投资学习 内容:看投资大佬访谈或演讲B站地址:巴菲特1998年佛州大学讲座目标:学习巴菲特的投资哲学和人生智慧时间:2小时评估:非常不错,值…...
人脑记忆机制与神经形态计算应用解析
1. 记忆存储的神经机制解析 人脑的记忆系统是一个精密的层级结构,从短暂的感官印象到持久的经验存储,整个过程涉及多个脑区的协同工作。短期记忆(Short-Term Memory, STM)就像一块随时会被擦除的白板,容量有限且易受干…...
海洋涡旋识别与追踪:如何用Python快速掌握海洋中尺度涡旋的完整分析流程?
海洋涡旋识别与追踪:如何用Python快速掌握海洋中尺度涡旋的完整分析流程? 【免费下载链接】py-eddy-tracker Eddy identification and tracking 项目地址: https://gitcode.com/gh_mirrors/py/py-eddy-tracker 你是否曾为海洋涡旋数据处理的复杂性…...
服务注册与发现完全指南
服务注册与发现完全指南 前言 在微服务架构中,服务注册与发现是实现服务间通信的基础设施。服务注册中心维护着所有服务的实例信息,使得服务消费者能够动态地发现和调用服务提供者。本文将详细介绍服务注册与发现的核心概念、实现机制以及最佳实践。 一、…...
通过用量看板清晰观测各模型API调用成本与消耗
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过用量看板清晰观测各模型API调用成本与消耗 效果展示类,介绍开发者在接入Taotoken后,如何通过平台提供的…...
Generative AI本质与企业落地实战指南
1. 这不是“AI画画”那么简单:Generative AI到底在生成什么、为什么突然爆发、谁该真正关注它Generative AI——这个词过去三年里高频出现在科技媒体、投资人会议、产品经理周报甚至咖啡馆闲聊中,但很多人至今仍把它等同于“用文字生成图片”或“让AI写周…...
【学习笔记】探讨大模型应用安全建设系列5——供应链安全与数据防护
供应链安全在大模型场景里很容易被低估。很多团队以为管好代码依赖就够了,但大模型应用的供应链比传统应用长得多——模型、Prompt、知识库、插件、外部 API 都是攻击面。 LiteLLM 事件证明:一个依赖包投毒,短时间内就可能扩散到大量…...
LRCGET:告别手动搜索,实现本地音乐歌词批量下载的完整指南
LRCGET:告别手动搜索,实现本地音乐歌词批量下载的完整指南 【免费下载链接】lrcget Utility for mass-downloading LRC synced lyrics for your offline music library. 项目地址: https://gitcode.com/gh_mirrors/lr/lrcget 你是否拥有大量本地音…...
长期使用Taotoken后对账单清晰度与成本预测的体会
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 长期使用Taotoken后对账单清晰度与成本预测的体会 效果展示类,分享作为长期用户,如何依赖Taotoken提供的详…...
【ElevenLabs广西话语音落地实战】:20年语音AI专家亲授3步绕过方言合成陷阱,97.3%自然度实测达标
更多请点击: https://intelliparadigm.com 第一章:ElevenLabs广西话语音落地实战总览 ElevenLabs 官方尚未提供原生广西话(粤语邕浔片/平话混合语境)语音模型,但通过其 API 的自定义语音微调(Fine-tuning&…...
Java类与对象:编程核心解密
好的,我们来详细解释一下Java中的类和对象这两个核心概念。1. 类 (Class)定义:类是一个模板或蓝图。它定义了某一类“事物”的共同特征(属性)和行为(方法)。作用:类描述了该种“事物”具有哪些信…...
