SpringBoot+MybatisPlus+Mysql实现批量插入万级数据多种方式与耗时对比

场景

若依前后端分离版本地搭建开发环境并运行项目的教程:

若依前后端分离版手把手教你本地搭建环境并运行项目_本地运行若依前后端分离-CSDN博客

若依前后端分离版如何集成的mybatis以及修改集成mybatisplus实现Mybatis增强:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/136203040

基于以上基础,测试批量将万级以上数据插入到mysql数据中的多种方式。

注:

博客:
霸道流氓气质-CSDN博客

实现

1、数据准备

参考上面集成mp时测试用的SysStudent表以及相关代码,每种方式执行前首先将数据库中

表清空。

application.yml中连接mysql的url中添加开启批处理模式的配置

&rewriteBatchedStatements=true

2、方式一:最基本的for循环批量插入的方式

直接使用mapper自带的insert方法使用for循环插入数据

编写单元测试

    @Testpublic void foreachInsertData() {StopWatch stopWatch = new StopWatch();stopWatch.start();for (int i = 0; i < 50000; i++) {SysStudent sysStudent = SysStudent.builder().studentName("test").studentAge(i).studentHobby("test").build();sysStudentMapper.insert(sysStudent);}stopWatch.stop();System.out.println(stopWatch.shortSummary());}

运行结果

时间较长,高达179秒,不推荐使用。

利用for循环进行单条插入时,每次都是在获取连接(Connection)、释放连接和资源关闭等操作上,

(如果数据量大的情况下)极其消耗资源,导致时间长。

当然所有测试时间均是在单元测试中进行,运行时间受多方面影响,不代表最终业务层运行实际时间,

仅用作同等条件方式下耗时对比。

3、方式二:使用拼接sql方式实现批量插入数据

在mapper中新增方法

public interface SysStudentMapper extends BaseMapper<SysStudent>
{@Insert("<script>" +"insert into sys_student (student_name, student_age, student_hobby) values " +"<foreach collection='studentList' item='item' separator=','> " +"(#{item.studentName}, #{item.studentAge},#{item.studentHobby}) " +"</foreach> " +"</script>")int insertSplice(@Param("studentList") List<SysStudent> studentList);
}

编写单元测试

    @Testpublic void spliceSqlInsertData() {ArrayList<SysStudent> students = new ArrayList<>();StopWatch stopWatch = new StopWatch();stopWatch.start();for (int i = 0; i < 50000; i++) {SysStudent sysStudent = SysStudent.builder().studentName("test").studentAge(i).studentHobby("test").build();students.add(sysStudent);}sysStudentMapper.insertSplice(students);stopWatch.stop();System.out.println(stopWatch.shortSummary());}

运行结果

拼接结果就是将所有的数据集成在一条SQL语句的value值上,其由于提交到服务器上的insert语句少了,网络负载少了,

性能也就提上去。但是当数据量上去后,可能会出现内存溢出、解析SQL语句耗时等情况。

4、方式三:使用mybatisplus的saveBatch实现批量插入

使用MyBatis-Plus实现IService接口中批处理saveBatch()方法

编写单元测试

    @Testpublic void batchInsertData() {ArrayList<SysStudent> students = new ArrayList<>();StopWatch stopWatch = new StopWatch();stopWatch.start();for (int i = 0; i < 50000; i++) {SysStudent sysStudent = SysStudent.builder().studentName("test").studentAge(i).studentHobby("test").build();students.add(sysStudent);}iSysStudentService.saveBatch(students,1000);stopWatch.stop();System.out.println(stopWatch.shortSummary());}

运行结果

5、方式四:共用SqlSession,关闭自动提交事务实现for循环批量插入大数据量数据

由于同一个SqlSession省去对资源相关操作的耗能、减少对事务处理的时间等,从而极大程度上提高执行效率。

编写单元测试

    @Testpublic void forBatchInsertData() {//开启批处理处理模式 BATCH,关闭自动提交事务SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH,false);//反射获取 MapperSysStudentMapper sysStudentMapper = sqlSession.getMapper(SysStudentMapper.class);StopWatch stopWatch = new StopWatch();stopWatch.start();for (int i = 0; i < 50000; i++) {SysStudent sysStudent = SysStudent.builder().studentName("test").studentAge(i).studentHobby("test").build();sysStudentMapper.insert(sysStudent);}//一次性提交事务sqlSession.commit();//关闭资源sqlSession.close();stopWatch.stop();System.out.println(stopWatch.shortSummary());}

引入依赖

    @Autowiredprivate SqlSessionFactory sqlSessionFactory;

运行结果

推荐使用

6、方式五:使用ThreadPoolTaskExecuror线程池实现批量插入大数据量数据到mysql

将要插入的数据列表按照指定的批次大小分割成多个子列表,并开启多个线程来执行插入操作。

通过 TransactionManager 获取事务管理器,并使用 TransactionDefinition 定义事务属性。

在每个线程中,我们通过 transactionManager.getTransaction() 方法获取事务状态,并在插入操作中使用该状态来管理事务。

在插入操作完成后,根据操作结果调用transactionManager.commit()或 transactionManager.rollback() 方法来提交或回滚事务。

在每个线程执行完毕后,都会调用 CountDownLatch 的 countDown() 方法,以便主线程等待所有线程都执行完毕后再返回。

Java中使用CountDownLatch实现并发流程控制:

Java中使用CountDownLatch实现并发流程控制_countdownlatch设置为几-CSDN博客

SpringBoot中使用Spring自带线程池ThreadPoolTaskExecutor与Java8CompletableFuture实现异步任务示例:

SpringBoot中使用Spring自带线程池ThreadPoolTaskExecutor与Java8CompletableFuture实现异步任务示例_spring boot taskexecutor-CSDN博客

编写单元测试:

    @Testpublic void threadPoolInsertData() {ArrayList<SysStudent> students = new ArrayList<>();StopWatch stopWatch = new StopWatch();stopWatch.start();for (int i = 0; i < 50000; i++) {SysStudent sysStudent = SysStudent.builder().studentName("test").studentAge(i).studentHobby("test").build();students.add(sysStudent);}int count = students.size();int pageSize = 1000; //每批次插入的数据量int threadNum = count%pageSize == 0?(count/pageSize):(count/pageSize+1); //线程数CountDownLatch countDownLatch = new CountDownLatch(threadNum);for (int i = 0; i < threadNum; i++) {int startIndex = i * pageSize;int endIndex = Math.min(count,(i+1)*pageSize);List<SysStudent> subList = students.subList(startIndex,endIndex);threadPoolTaskExecutor.execute(()->{DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(transactionDefinition);try{sysStudentMapper.insertSplice(subList);transactionManager.commit(status);}catch (Exception exception){transactionManager.rollback(status);throw exception;}finally {countDownLatch.countDown();}});}try{countDownLatch.await();}catch (InterruptedException e){e.printStackTrace();}stopWatch.stop();System.out.println(stopWatch.shortSummary());}

需要引入依赖

    @Autowiredprivate ThreadPoolTaskExecutor threadPoolTaskExecutor;@Autowiredprivate PlatformTransactionManager transactionManager;

运行结果

推荐使用



      

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Open AI 的 Sora 是什么?它是如何工作的?应用场景、风险、替代方案、未来意义等

Open AI 的 Sora 是什么&#xff1f;它是如何工作的&#xff1f;应用场景、风险、替代方案、未来意义等 探索 OpenAI 的 Sora&#xff1a;一种突破性的文本到视频 AI&#xff0c;将在 2024 年彻底改变多模态人工智能。探索其功能、创新和潜在影响。 OpenAI 最近宣布了其最新的突…

【后端】springboot项目

文章目录 1. 2.3.7.RELEASE版本搭建1.1 pom文件1.1.1 方式一1.1.2 方式二 1.2 启动类1.3 测试类 2. 引入Value乱码问题解决 【后端目录贴】 1. 2.3.7.RELEASE版本搭建 1.1 pom文件 1.1.1 方式一 <parent><groupId>org.springframework.boot</groupId><…

28/100二叉树的中序遍历 29/100不同的二叉搜索树(TODO) 30/100验证二叉搜索树 31/100对称二叉树

题目&#xff1a;28/100 二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 题解&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() …

gitlab 项目上线,项目上线后回滚

gitlab 项目上线&#xff0c;项目上线后回滚 1.需要自己有个gitlab项目环境&#xff0c;没有找我&#xff0c;docker-compose 一键环境启动 2.发起合并请求3.选择合并的分支4.点击创建合并&#xff0c;然后确认合并合并完成&#xff0c;进行回滚操作&#xff0c;在合并详情页…

leetcode 148. 排序链表 java解法

Problem: 148. 排序链表 思路 这是一个链表排序的问题&#xff0c;由于要求时间复杂度为 O(nlogn)&#xff0c;适合使用归并排序&#xff08;Merge Sort&#xff09;来解决。 解题方法 首先&#xff0c;使用快慢指针找到链表的中间节点&#xff0c;将链表分成两部分。然后&…

Vue | (三)使用Vue脚手架(下)| 尚硅谷Vue2.0+Vue3.0全套教程

文章目录 &#x1f4da;Vue 中的自定义事件&#x1f407;使用方法&#x1f407;案例练习&#x1f407;TodoList案例优化 &#x1f4da;全局事件总线&#x1f407;使用方法&#x1f407;案例练习&#x1f407;TodoList案例优化 &#x1f4da;消息订阅与发布&#x1f407;使用方法…

压缩感知常用的测量矩阵

测量矩阵的基本概念 在压缩感知&#xff08;Compressed Sensing&#xff0c;CS&#xff09;理论中&#xff0c;测量矩阵&#xff08;也称为采样矩阵&#xff09;是实现信号压缩采样的关键工具。它是一个通常为非方阵的矩阵&#xff0c;用于将信号从高维空间映射到低维空间&…

10、内网安全-横向移动域控提权NetLogonADCSPACKDC永恒之蓝

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 背景&#xff1a; 主要针对内网主机中的 域控提权漏洞&#xff0c;包含漏洞探针和漏洞复现利用。 1、横向移动-系统漏洞-CVE-2017-0146&#xff08;ms17-010&#xff0c;永恒之蓝&#xff0…

微信小程序 --- 通用模块封装(showToast,showModal ,本地存储)

目录 01. 为什么进行模块封装 02. 消息提示模块封装 03. 模态对话框封装 04. 封装本地存储 API 05. 拓展:封装异步存储API优化代码 01. 为什么进行模块封装 在进行项目开发的时候&#xff0c;我们经常的会频繁的使用到一些 API&#xff0c; 例如&#xff1a;wx.showToast…

docker 备份 mysql

使用 Docker 执行 MySQL 备份是一个实用的操作&#xff0c;可以帮助你确保数据的安全性和可恢复性。这里有一步步的指导帮你完成&#xff1a; 1. 确定 MySQL 容器名称或 ID 首先&#xff0c;你需要知道运行 MySQL 数据库的容器的名称或 ID。可以通过下面的命令查看所有正在运…

彩虹工具网程序开源未加密版源码,支持插件扩展

全新UI彩虹站长在线工具箱系统源码下载 全开源版本 支持暗黑模式 支持高达72种站长工具、开发工具、娱乐工具等功能。本地调用API、自带免费API接口&#xff0c; 是一个多功能性工具程序支持后台管理、上传插件、添加增减删功能 下载地址你别走吖 Σ(っ Д ;)っ (chaobiji.c…

Android13 编译ninja failed with: exit status 137

描述 现象很奇怪&#xff0c;主机是ubuntu 18.04&#xff0c; 内存有32G&#xff0c;并且系统中有两份Android13代码&#xff0c; 有一份编译正常&#xff0c;另外一份编译不正常&#xff0c;一度以为是因为下载源码不齐全导致&#xff0c;后面仔细看日志&#xff0c;原来是内…

Windows Server 2012 安装

1.镜像安装 镜像安装:Windows Server 2012 2.安装过程(直接以图的形式呈现) 2012激活秘钥:J7TJK-NQPGQ-Q7VRH-G3B93-2WCQD

WatiN——Web自动化测试(一)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

单例设计模式Singleton

1.模式定义 保证一个类只有一个实例&#xff0c;并且提供一个全局访问点 2.应用场景 重量级的对象&#xff0c;不需要多个实例&#xff0c;如线程池&#xff0c;数据库连接池。 2.1 源码中的应用 // Spring & JDK java.lang.Runtime org.springframework.aop.framework.Pro…

Linux:gitlab创建组,创建用户,创建项目

创建组和项目 让后可以在组里创建一个个仓库 创建成员 我创建个成员再把他分配进这个组里 进入管理员 密码等会我们创建完用户再去配置密码 Regular是普通的用户&#xff0c;只可以正常去访问指定规则的项目 而下面的administrator就是管理员&#xff0c;可以随便进项目&…

游戏开发速成入门

0&#xff0c;前言 两计算机专业菜鸡在大一到大二期间玩儿的游戏开发这一块的碰壁经验&#xff0c;从建模到游戏开发到c开发过渡的通俗基础参考&#xff0c;单纯玩玩儿可以参考本文Hah.。 by jzy/hzh 1&#xff0c;BLENDER 1.1流程推荐&#x…

基于springboot+vue的B2B平台的购物推荐网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

线阵相机参数介绍---变频参数控制

变频器介绍 变频器功能的目的在于对外部输入信号进行运算处理&#xff0c;以达到理想的行频值。该功能主要是为了解决信号超行频&#xff0c;图像拉伸压缩等问题。 输入信号处理过程&#xff1a; 输入信号&#xff1a;允许出发相机信号的频率f与所要求输入信号的频率F不同 …

基于Web的网文管理系统

项目&#xff1a;基于Web的网文管理系统 伴随着时代的更替&#xff0c;我国人民的生活水平在不断提高&#xff0c;同时对生活娱乐的需求也在不断加大&#xff0c;我们在日常生活中通常会以多种方式娱乐自己&#xff0c;而阅读网络小说就是其中一种方式。随着计算机技术的成熟&a…