0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MySQL批量插入数据的四种方案(性能测试对比)

Android编程精选 来源:CSDN技术社区 作者:CSDN技术社区 2022-10-28 09:43 次阅读

本文记录个人使用MySQL插入大数据总结较实用的方案,通过对常用插入大数据的4种方式进行测试,即for循环单条、拼接SQL、批量插入saveBatch()、循环 + 开启批处理模式,得出比较实用的方案心得。

一、前言

最近趁空闲之余,在对MySQL数据库进行插入数据测试,对于如何快速插入数据的操作无从下手,在仅1W数据量的情况下,竟花费接近47s,实在不忍直视!在不断摸索之后,整理出一些较实用的方案。

二、准备工作

测试环境:SpringBoot项目、MyBatis-Plus框架、MySQL8.0.24、JDK13

前提:SpringBoot项目集成MyBatis-Plus上述文章有配置过程,同时实现IService接口用于进行批量插入数据操作saveBatch()方法

1、Maven项目中pom.xml文件引入的相关依赖如下



 

org.springframework.boot
spring-boot-starter-web


 

com.baomidou
mybatis-plus-boot-starter
3.3.1


 

mysql
mysql-connector-java


 

org.projectlombok
lombok



2、application.yml配置属性文件内容(重点:开启批处理模式)

server:
#端口号
port:8080

#MySQL连接配置信息(以下仅简单配置,更多设置可自行查看)
spring:
datasource:
#连接地址(解决UTF-8中文乱码问题+时区校正)
#(rewriteBatchedStatements=true开启批处理模式)
url:jdbc//127.0.0.1:3306/bjpowernode?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
#用户名
username:root
#密码
password:xxx
#连接驱动名称
driver-class-name:com.mysql.cj.jdbc.Driver

3、Entity实体类(测试)

/**
*Student测试实体类
*
*@Data注解:引入Lombok依赖,可省略Setter、Getter方法
*@authorLBF
*@date2022/3/1816:06
*/
@Data
@TableName(value="student")
publicclassStudent{

/**主键type:自增*/
@TableId(type=IdType.AUTO)
privateintid;

/**名字*/
privateStringname;

/**年龄*/
privateintage;

/**地址*/
privateStringaddr;

/**地址号@TableField:与表字段映射*/
@TableField(value="addr_num")
privateStringaddrNum;

publicStudent(Stringname,intage,Stringaddr,StringaddrNum){
this.name=name;
this.age=age;
this.addr=addr;
this.addrNum=addrNum;
}
}

4、数据库student表结构(注意:无索引)

f637d748-5608-11ed-a3b6-dac502259ad0.png

三、测试工作

简明:完成准备工作后,即对for循环、拼接SQL语句、批量插入saveBatch()、循环插入+开启批处理模式,该4种插入数据的方式进行测试性能。

注意:测试数据量为5W、单次测试完清空数据表(确保不受旧数据影响)

以下测试内容可能受测试配置环境、测试规范和数据量等诸多因素影响,读者可自行结合参考进行测试

1、for循环插入(单条)(总耗时:177秒)

总结:测试平均时间约是177秒,实在是不忍直视(捂脸),因为利用for循环进行单条插入时,每次都是在获取连接(Connection)、释放连接和资源关闭等操作上,(如果数据量大的情况下)极其消耗资源,导致时间长。

@GetMapping("/for")
publicvoidforSingle(){
//开始时间
longstartTime=System.currentTimeMillis();
for(inti=0;i< 50000; i++){
        Student student = new Student("李毅" + i,24,"张家界市" + i,i + "号");
        studentMapper.insert(student);
    }
    // 结束时间
    long endTime = System.currentTimeMillis();
    System.out.println("插入数据消耗时间:" + (endTime - startTime));
}

(1)第一次测试结果:190155 约等于 190秒

f666ff0a-5608-11ed-a3b6-dac502259ad0.png

(2)第二次测试结果:175926 约等于 176秒(服务未重启)

f67bef8c-5608-11ed-a3b6-dac502259ad0.png

(3)第三次测试结果:174726 约等于 174秒(服务重启)

f69ac7e0-5608-11ed-a3b6-dac502259ad0.png

2、拼接SQL语句(总耗时:2.9秒)

简明:拼接格式:insert into student(xxxx) value(xxxx),(xxxx),(xxxxx).......

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

但是当数据量上去后,可能会出现内存溢出、解析SQL语句耗时等情况,但与第一点相比,提高了极大的性能。

@GetMapping("/sql")
publicvoidsql(){
ArrayListarrayList=newArrayList<>();
longstartTime=System.currentTimeMillis();
for(inti=0;i< 50000; i++){
        Student student = new Student("李毅" + i,24,"张家界市" + i,i + "号");
        arrayList.add(student);
    }
    studentMapper.insertSplice(arrayList);
    long endTime = System.currentTimeMillis();
    System.out.println("插入数据消耗时间:" + (endTime - startTime));
}
//使用@Insert注解插入:此处为简便,不写Mapper.xml文件
@Insert("")
intinsertSplice(@Param("studentList")ListstudentList);

(1)第一次测试结果:3218 约等于 3.2秒

f6b57d9c-5608-11ed-a3b6-dac502259ad0.png

(2)第二次测试结果:2592 约等于 2.6秒(服务未重启)

f6ccc786-5608-11ed-a3b6-dac502259ad0.png

(3)第三次测试结果:3082 约等于 3.1秒(服务重启)

f6e4dfc4-5608-11ed-a3b6-dac502259ad0.png

3、批量插入saveBatch(总耗时:2.7秒)

简明:使用MyBatis-Plus实现IService接口中批处理saveBatch()方法,对底层源码进行查看时,可发现其实是for循环插入,但是与第一点相比,为什么性能上提高了呢?因为利用分片处理(batchSize = 1000) + 分批提交事务的操作,从而提高性能,并非在Connection上消耗性能。

@GetMapping("/saveBatch1")
publicvoidsaveBatch1(){
ArrayListarrayList=newArrayList<>();
longstartTime=System.currentTimeMillis();
//模拟数据
for(inti=0;i< 50000; i++){
        Student student = new Student("李毅" + i,24,"张家界市" + i,i + "号");
        arrayList.add(student);
    }
    // 批量插入
    studentService.saveBatch(arrayList);
    long endTime = System.currentTimeMillis();
    System.out.println("插入数据消耗时间:" + (endTime - startTime));
}

(1)第一次测试结果:2864 约等于 2.9秒

f6f9376c-5608-11ed-a3b6-dac502259ad0.png

(2)第二次测试结果:2302 约等于 2.3秒(服务未重启)

f711f1da-5608-11ed-a3b6-dac502259ad0.png

(3)第三次测试结果:2893 约等于 2.9秒(服务重启)

f725f680-5608-11ed-a3b6-dac502259ad0.png

重点注意:MySQL JDBC驱动默认情况下忽略saveBatch()方法中的executeBatch()语句,将需要批量处理的一组SQL语句进行拆散,执行时一条一条给MySQL数据库,造成实际上是分片插入,即与单条插入方式相比,有提高,但是性能未能得到实质性的提高。

测试:数据库连接URL地址缺少 rewriteBatchedStatements = true 参数情况

#MySQL连接配置信息
spring:
datasource:
#连接地址(未开启批处理模式)
url:jdbc//127.0.0.1:3306/bjpowernode?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
#用户名
username:root
#密码
password:xxx
#连接驱动名称
driver-class-name:com.mysql.cj.jdbc.Driver

测试结果:10541 约等于 10.5秒(未开启批处理模式)

f737150a-5608-11ed-a3b6-dac502259ad0.png

4、循环插入 + 开启批处理模式(总耗时:1.7秒)(重点:一次性提交)

简明:开启批处理,关闭自动提交事务,共用同一个SqlSession之后,for循环单条插入的性能得到实质性的提高;由于同一个SqlSession省去对资源相关操作的耗能、减少对事务处理的时间等,从而极大程度上提高执行效率。(目前个人觉得最优方案)

@GetMapping("/forSaveBatch")
publicvoidforSaveBatch(){
//开启批量处理模式BATCH、关闭自动提交事务false
SqlSessionsqlSession=sqlSessionFactory.openSession(ExecutorType.BATCH,false);
//反射获取,获取Mapper
StudentMapperstudentMapper=sqlSession.getMapper(StudentMapper.class);
longstartTime=System.currentTimeMillis();
for(inti=0;i< 50000 ; i++){
        Student student = new Student("李毅" + i,24,"张家界市" + i,i + "号");
        studentMapper.insertStudent(student);
    }
    // 一次性提交事务
    sqlSession.commit();
    // 关闭资源
    sqlSession.close();
    long endTime = System.currentTimeMillis();
    System.out.println("总耗时: " + (endTime - startTime));
}

(1)第一次测试结果:1831 约等于 1.8秒

f74cf744-5608-11ed-a3b6-dac502259ad0.png

(2)第二次测试结果:1382 约等于 1.4秒(服务未重启)

f761abb2-5608-11ed-a3b6-dac502259ad0.png

(3)第三次测试结果:1883 约等于 1.9秒(服务重启)

f776d226-5608-11ed-a3b6-dac502259ad0.png

四、总结

本文记录个人学习MySQL插入大数据一些方案心得,可得知主要是在获取连接、关闭连接、释放资源和提交事务等方面较耗能,其中最需要注意是开启批处理模式,即URL地址的参数:rewriteBatchedStatements = true,否则也无法发挥作用。

对于测试方案的设定、对考虑不周、理解和编写错误的地方等情况,请多指出,共同学习!

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据库
    +关注

    关注

    7

    文章

    3584

    浏览量

    63344
  • spring
    +关注

    关注

    0

    文章

    332

    浏览量

    14150
  • MySQL
    +关注

    关注

    1

    文章

    773

    浏览量

    25976

原文标题:MySQL批量插入数据的四种方案(性能测试对比)

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    FPGA 设计的四种常用思想与技巧

    FPGA 设计的四种常用思想与技巧FPGA设计的四种常用思想与技巧 讨论的四种常用FPGA/CPLD设计思想与技巧:乒乓操作、串并转换、流水线操作、数据接口同步化,都是FPGA/CP
    发表于 08-11 10:30

    MySQL和MongoDB的对比

    IT技术社区)概要 关系型数据库已经成为企业应用程序的基础,自从MySQL在1995年发布以来,它已经成为一受欢迎并且廉价的选择。然而随着近年来数据量和
    发表于 08-28 14:51

    数据四种思维方式

    数据所带来的四种思维方式的转变
    发表于 08-12 11:37

    labview插入数据MySQL数据

    最近在用labview写入数据MySQL数据库,遇到一个问题:(如图片所示)利用insert指令插入数据,为什么每次
    发表于 12-26 16:52

    USB的四种传输类型

    `USB的四种传输类型1.控制传输:控制传输是一可靠的双向传输,一次控制传输可分为三个阶段。第一阶段为从HOST到Device的SETUP事务传输,这个阶段指定了此次控制传输的请求类型;第二阶段为
    发表于 10-09 09:36

    几种数据库的大数据批量插入解决方法

    在之前只知道SqlServer支持数据批量插入,殊不知道Oracle、SQLite和MySql也是支持的,不过Oracle需要使用Orace.DataAccess驱动,今天就贴出几种
    发表于 11-04 07:59

    四种主要的负电源轨生成方案如何选择

    四种主要的负电源轨生成方案如何选择
    发表于 03-11 06:00

    ModBus四种数据DI/DO/AI/AO是什么?

    ModBus四种数据DI/DO/AI/AO是什么?
    发表于 11-02 07:14

    SPI的四种时序

    声明:本篇文章面向在已对SPI的四种时序有所了解的人我们采用SPI3模式以及将FPGA作从机,STM32作主机的方式讲解,在STM32控制部分采用的是半双工模式,但其实半双工与全双工区别不大,稍加
    发表于 02-09 06:18

    为什么四种DDR验证BIST测试类型无法执行并且颜色编码指示?

    你好任何人都可以解释为什么四种 DDR 验证 BIST 测试类型无法执行并且颜色编码指示“…………测试脚本中的错误”?我能够成功执行 DDR 验证阶段和其他四种 DDR 验证
    发表于 04-06 08:54

    MySQL数据库:如何操作禁止重复插入数据

    MySQL进行数据插入操作时,总是会考虑是否会插入重复数据,之前的操作都是先根据主键或者唯一约束条件进行查询,有就进行更新没有就进行
    的头像 发表于 10-08 14:15 2992次阅读
    <b class='flag-5'>MySQL</b><b class='flag-5'>数据</b>库:如何操作禁止重复<b class='flag-5'>插入</b><b class='flag-5'>数据</b>

    MySQL 5.7与MySQL 8.0 性能对比

    背景 测试mysql5.7和mysql8.0分别在读写,选定,只写模式下不同并发时的性能(tps,qps) 最早 测试使用版本为
    的头像 发表于 11-03 09:26 1.4w次阅读
    <b class='flag-5'>MySQL</b> 5.7与<b class='flag-5'>MySQL</b> 8.0 <b class='flag-5'>性能对比</b>

    MySQL 批量插入不重复数据的解决方法

    业务很简单:需要批量插入一些数据数据来源可能是其他数据库的表,也可能是一个外部excel的导入
    的头像 发表于 07-02 15:28 2054次阅读
    <b class='flag-5'>MySQL</b> <b class='flag-5'>批量</b><b class='flag-5'>插入</b>不重复<b class='flag-5'>数据</b>的解决方法

    MyBatis批量插入数据的3种方法你知道几种

    批量插入功能是我们日常工作中比较常见的业务功能之一, 今天 来一个 MyBatis 批量插入的汇总篇,同时对 3 种实现方法做一个性能
    的头像 发表于 12-08 17:56 3715次阅读
    MyBatis<b class='flag-5'>批量</b><b class='flag-5'>插入</b><b class='flag-5'>数据</b>的3种方法你知道几种

    MySQL在执行批量操作的时候一次插入多少数据才合适呢?

    我们在操作大型数据表或者日志文件的时候经常会需要写入数据数据库,那么最合适的方案就是数据库的批量
    的头像 发表于 01-31 14:09 6503次阅读