Mysql批量插入对比(附github仓库demo)

news2025/1/9 2:43:00

前言

本文记录个人使用MySQL插入大数据总结较实用的方案,通过对常用插入大数据的4种方式进行测试,

  • for循环单条
  • 拼接SQL
  • 批量插入saveBatch()
  • 循环 + 开启批处理模式
    最近趁空闲之余,在对MySQL数据库进行插入数据测试

准备工作

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

创建springboot项目和数据库

github:demo代码地址
maven依赖
pom

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.cainiao</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springboot-save-batch</artifactId>
    <packaging>jar</packaging>

    <name>springboot-save-batch</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>
        <!--mybatisPlus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
            <scope>compile</scope>
        </dependency>
        <!--lombok :getter/setter方法以及构造器的生成 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 引入阿里数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

applocation.yml


# 配置端口
server:
  port: 8089
  servlet:
    context-path: /caimiao
spring:
  # 配置数据源
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cainiao?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&sessionVariables=sql_mode=NO_ENGINE_SUBSTITUTION
    username: root
    password: 123456
#    type: com.alibaba.druid.pool.DruidDataSource
#  druid:
#    initialSize: 5 #初始化连接大小
#    minIdle: 5     #最小连接池数量
#    maxActive: 20  #最大连接池数量
#    maxWait: 60000 #获取连接时最大等待时间,单位毫秒
#    timeBetweenEvictionRunsMillis: 60000 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
#    minEvictableIdleTimeMillis: 300000   #配置一个连接在池中最小生存的时间,单位是毫秒
#    validationQuery: SELECT 1 from DUAL  #测试连接
#    testWhileIdle: true                  #申请连接的时候检测,建议配置为true,不影响性能,并且保证安全性
#    testOnBorrow: false                  #获取连接时执行检测,建议关闭,影响性能
#    testOnReturn: false                  #归还连接时执行检测,建议关闭,影响性能
#    poolPreparedStatements: false        #是否开启PSCache,PSCache对支持游标的数据库性能提升巨大,oracle建议开启,mysql下建议关闭
#    maxPoolPreparedStatementPerConnectionSize: 20 #开启poolPreparedStatements后生效
#    filters: stat,wall,log4j #配置扩展插件,常用的插件有=>stat:监控统计  log4j:日志  wall:防御sql注入
#    connectionProperties: 'druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000' #通过connectProperties属性来打开mergeSql功能;慢SQL记录


# mybatis-plus相关配置
mybatis-plus:
  # xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)
  mapper-locations: classpath:mapper/*.xml
  # 以下配置均有默认值,可以不设置
  global-config:
    db-config:
      #主键类型 AUTO:"数据库ID自增" INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
      id-type: auto
      #字段策略 IGNORED:"忽略判断"  NOT_NULL:"非 NULL 判断")  NOT_EMPTY:"非空判断"
      field-strategy: NOT_EMPTY
      #数据库类型
      db-type: MYSQL
  configuration:
    # 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
    map-underscore-to-camel-case: true
    # 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
    call-setters-on-nulls: true
    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

swagger:
  enable: true

实验数据库表创建

CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `addr` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


开始测试

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

向数据库中插入5w条数据

for循环

@GetMapping("for")
    public void saveStudent(){
        // 开始时间
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++){
            Student student = new Student();
            student.setName("张三" + i);
            student.setAge(i);
            student.setAddr("北京市第"+i+"街道");
            studentDao.insert(student);
        }
        // 结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("插入数据消耗时间:" + (endTime - startTime));
    }

执行耗时:222080 大约222秒
在这里插入图片描述

拼接sql

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

@ApiOperation("sql批量插入")
    @GetMapping("sql")
    public void saveSqlStudent(){
        // 开始时间
        long startTime = System.currentTimeMillis();
        List<Student> studentList = new ArrayList<>();
        for (int i = 0; i < 50000; i++){
            Student student = new Student();
            student.setName("李四" + i);
            student.setAge(i);
            student.setAddr("北京市第"+i+"街道");
            studentList.add(student);
        }
        studentDao.saveList(studentList);
        // 结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("插入数据消耗时间:" + (endTime - startTime));
    }

Dao:

void saveList(@Param("list") List<Student> studentList);

mapper.xml

 <insert id="saveList">
        INSERT INTO student(name,age,addr)  VALUES
        <foreach collection="list" item="item" index="index" separator=",">
        (#{item.name},
        #{item.age},
        #{item.addr})
        </foreach>

    </insert>

执行时间:2971 大约2.9秒

在这里插入图片描述

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

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

批量插入saveBatch

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

  @ApiOperation("batch批量插入")
    @GetMapping("batch")
    public void saveBatchStudent(){
        // 开始时间
        long startTime = System.currentTimeMillis();
        List<Student> studentList = new ArrayList<>();
        for (int i = 0; i < 50000; i++){
            Student student = new Student();
            student.setName("李四" + i);
            student.setAge(i);
            student.setAddr("北京市第"+i+"街道");
            studentList.add(student);
        }
        studentDao.saveList(studentList);
        // 结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("插入数据消耗时间:" + (endTime - startTime));
    }

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

所以需要数据库链接开启rewriteBatchedStatements = true
我们开启之后再执行一遍:

    url: jdbc:mysql://localhost:3306/cainiao?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&rewriteBatchedStatements=true&useSSL=false&serverTimezone=GMT%2B8&sessionVariables=sql_mode=NO_ENGINE_SUBSTITUTION

执行时间:85155 约85秒
在这里插入图片描述

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

@ApiOperation("forSaveBatch批量插入")
    @GetMapping("/forSaveBatch")
    public void forSaveBatch(){
        //  开启批量处理模式 BATCH 、关闭自动提交事务 false
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH,false);
        //  反射获取,获取Mapper
        StudentDao studentMapper = sqlSession.getMapper(StudentDao.class);
        long startTime = System.currentTimeMillis();
        for (int i = 0 ; i < 50000 ; i++){
            Student student = new Student();
            student.setName("王五" + i);
            student.setAge(i);
            student.setAddr("北京市第"+i+"街道");
            studentMapper.insert(student);
        }
        // 一次性提交事务
        sqlSession.commit();
        // 关闭资源
        sqlSession.close();
        long endTime = System.currentTimeMillis();
        System.out.println("总耗时: " + (endTime - startTime));
    }

执行时间:99530 约99秒
在这里插入图片描述

总结

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

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

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

相关文章

189:vue+openlayers 上传CSV文件,导出Geojson格式文件

第189个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers上传CSV文件,导出GeoJSON文件。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果OpenStreetMap无法加载,请加载其他来练习 文章目录 示例效果使用的csv文件安装依赖配置方…

直播场控助手 | 为什么说直播场控比主播更重要?

在竞争白热化的直播时代&#xff0c;作为主播最亲密的伙伴&#xff0c;场控的作用不容忽视。 优秀的场控掌握着关键成交节点&#xff0c;实时帮助主播带节奏、促转化。在精细化直播运营中&#xff0c;优秀的场控能力胜过十位主播&#xff0c;让直播间轻松实现销量翻倍。 「帷幄…

基于jsp+mysql+ssm水果蔬菜销售系统-计算机毕业设计

项目介绍 生活中&#xff0c;人们买水果或者蔬菜都是去菜市场买&#xff0c;因为那里是卖水果、蔬菜的聚集地。农商们把水果、蔬菜从远处运到那里&#xff0c;进行销售。但是这种销售方式的不足在于每次运输的数量是有限的&#xff0c;并且运输过程中也影响了水果、蔬菜的口感…

使用 TVMC 编译和优化模型

内容一览&#xff1a;本节讲解使用 TVMC 编译和优化模型。TVMC 是 TVM 的命令驱动程序&#xff0c;通过命令行执行 TVM 功能。本节是了解 TVM 工作原理的基础。 关键词&#xff1a;TVMC TVM 机器学习 本节将介绍 TVMC&#xff08;TVM 的命令行驱动程序&#xff09;。TVM…

单片机扫盲

一、从电路到集成电路 集成电路&#xff1a;使用微器件为“积木”&#xff0c;去搭建一个具备一定功能的电路板 微器件出现之前&#xff0c;一个电路功能需要很大一块电路板才能实现&#xff0c;有了微器件电路板的体积可以降到mm级别。 IC芯片就是将电路的所有微器件集成到一…

大数据时代,数据仓库究竟是干嘛的?

前言 无论你是否专门从事大数据开发&#xff0c;作为一个开发人员&#xff0c;应该都听说过数据仓库的概念&#xff0c;那你知道为什么会出现数据仓库&#xff1f;数据仓库究竟是干嘛的吗&#xff1f;有什么价值和意义呢&#xff1f;那么本文就带到入门&#xff0c;揭开数据仓…

大数据分析工具-FineReport地产行业通用单选按钮组控件插件

1. 概述 1.1 版本 报表服务器版本 JAR 包版本 插件版本 10.0 2018-09-05 V1.3.4 9.0 2015-08-09 V1.3.2 8.0 2015-08-09 V1.3.2 1.2 应用场景 地产行业具有比较特殊的筛选需求&#xff0c;而现有的单选按钮组控件不能很好的满足这一点。我们希望可以实现多层级多…

空间音频技术与生态发展高峰论坛成功举办,业界首个Audio Vivid创作工具花瓣三维声亮相

11月26日至27日&#xff0c;UWA世界超高清视频产业联盟&#xff08;以下简称“UWA联盟”&#xff09;、上海交通大学-南加州大学文化创意产业学院、华为联合举办了“互联智慧&#xff0c;共赢未来” 超高清音视频技术与生态发展高峰论坛暨Audio Vivid空间音频工具花瓣三维声训练…

Nocas环境隔离

Nocas环境隔离配置 为了做数据和服务的管理&#xff0c;引出了环境隔离的一个概念。 Nocas中服务存储和数据存储的最外层都是一个名为namespace的东西&#xff0c;用来做最外层隔离。 .yml 配置文件中配置&#xff1a; spring:application:name: orderservicecloud:nacos:se…

OH----Usb rndis,mtp等function添加,config配置

1、驱动侧添加对应功能的驱动代码&#xff1a; 在linux中usb驱动代码中添加rndis或者mtp等功能驱动代码&#xff0c; 路径&#xff1a; linux-5.10/drivers/usb/gadget/function linux usb驱动原生功能代码一般可以直接使用&#xff0c;添加进去参与编译就能继续往下做调试了&…

【校招项目】基于C++11的muduo库

基于C11的网络库 文章目录基于C11的网络库项目介绍项目地址项目特点开发环境并发模型构建项目运行案例模块讲解ChannelPollerEventLoopBufferTimerHTTP异步日志内存池数据库连接池优化计划感谢项目介绍 本项目是参考 muduo 实现的基于 Reactor 模型的多线程网络库。使用 C 11 …

如何高效存储中高频多因子

2022年12月1日晚7点半&#xff0c;DolphinDB 进行了以「中高频多因子库存储最佳实践」为主题的直播&#xff0c;吸引了众多专业观众的注意。本文将回顾直播精彩内容。 DolphinDB 的因子库&#xff1a; 为了使广大用户更方便地实现因子计算和管理&#xff0c;助力更高效的投研…

[附源码]Node.js计算机毕业设计大学生专业实习管理系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

C/C++ 高精度(加减乘除)算法简单实现

文章目录前言一、基本原理1、存储方式2、计算方式二、辅助方法1、字符串转高精度2、整型转高精度3、比较4、打印三、算法实现1、加法2、减法3、乘法4、除法四、使用示例1、加法2、减法3、乘法4、除法总结前言 由于上一章《C/C 高精度&#xff08;加减乘除&#xff09;算法实现…

NetSuite资产负债表编制技巧

在最近的项目上&#xff0c;发现大家对NetSuite资产负债的编制参数缺乏足够的了解&#xff0c;导致对客户需求的支支吾吾&#xff0c;产生了沟通上的浪费。所以今朝对三个典型应用做个介绍。 1. 如何在资产负债表中选择“会计期间区间”&#xff1f; 2. 期初、发生、结余报表…

【元宇宙欧米说】Web3如何为漫画产业创造更多玩法和可能性

漫画和NFT的碰撞会产生什么火花&#xff1f;NFT如何为传统的漫画收藏增加额外价值&#xff1f;Web3时代如何为漫画带来更多玩法和可能性&#xff1f; 12月15日下午三点&#xff0c;MadManga 创始人Jun将以“Web3如何为漫画产业创造更多玩法和可能性”为题&#xff0c;与大家共…

构建文本摘要Baseline并且开始训练

构建文本摘要Baseline并且开始训练 基于前面word2vec的原理与训练实践、seq2seq模型的原理与实践以及attention机制&#xff0c;已经分别写了相关的文章来记录&#xff0c;此篇文章就是基于前面所学&#xff0c;开始着手训练文本摘要模型&#xff0c;当然仅是一个比较普通的ba…

[附源码]Node.js计算机毕业设计大学体育馆预约系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

vue框架搭建大屏自适应方案

vue框架搭建大屏自适应方案 1.可使用flexible.js rem实现宽高&#xff0c;字体自适应 附上flexible.js代码 (function flexible(window, document) {var docEl document.documentElement;var dpr window.devicePixelRatio || 1;// adjust body font sizefunction setBody…

NocasRule负载均衡与服务实例的权重设置

NocasRule负载均衡 .yml 配置文件配置 server:port: 8080 spring:application:name: orderservicecloud:nacos:server-addr: localhost:8848 #nocas服务地址discovery:cluster-name: HZ #集群名字 userservice: #要做配置的微服务名称ribbon:NFLoadBalancerRuleClassName: com…