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小时评估:非常不错,值…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...

rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...