MySQL插入大量数据探讨
笔者想进行数据库查询优化探索,但是前提是需要一个很大的表,因此得先导入大量数据至一张表中。
准备工作
准备一张表,id为主键且自增:

方案一
首先我想到的方案就是通过for循环插入
xml文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zy.route.mapper.BigBiaoMapper"> <resultMap id="BaseResultMap" type="com.zy.route.DO.BigBiao">
<id column="id" property="id"/>
<result column="menu" property="menu"/>
<result column="operation" property="operation"/>
<result column="uri" property="uri"/>
<result column="msg" property="msg"/>
<result column="creator" property="creator"/>
</resultMap> <sql id="tableName">
bigbiao
</sql> <sql id="BaseColumn">
`id`, `menu`, `operation`, `uri`, `msg`,`creator`
</sql> <sql id="set">
<if test="id != null">
`id` = #{id},
</if>
<if test="menu != null">
`menu` = #{menu},
</if>
<if test="operation != null">
`operation` = #{operation},
</if>
<if test="uri != null">
`uri` = #{uri},
</if>
<if test="msg != null">
`msg` = #{msg},
</if>
<if test="creator != null">
`creator` = #{creator},
</if>
</sql> <insert id="insertIntoBiao" parameterType="com.zy.route.DO.BigBiao">
insert
<include refid="tableName"/>
<set>
<include refid="set"/>
</set>
</insert> </mapper>
这里我就直接使用SpringBoot的测试类进行插入操作
@SpringBootTest
@RunWith(SpringRunner.class)
public class BigBiaoMapperTest { @Autowired
private BigBiaoMapper bigBiaoMapper; @Test
public void insert() {
BigBiao bigBiao = new BigBiao()
.setMenu("项目资料")
.setOperation("查询项目目录")
.setUri("/project/big/biao")
.setMsg("{\"method\":\"Get\"\",\"\"costTime:95\"\",\"\"ip:255.255.255.0\"}")
.setCreator("LonZyuan");
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
bigBiaoMapper.insertIntoBiao(bigBiao);
}
long end = System.currentTimeMillis();
System.out.println("执行时间:" + (end - start) + "ms");
}
}
执行,查看执行时间:

可以发现,就单单1000条数据,就花了29s多
原因分析(参考MySQL45讲)
首先我们需要了解一条SQL更新语句是如何执行的:

而我方案一中的操作就是,通过for循环,进行了1000次的客户端与数据库的开闭连接,然后每次就写入一条数据,
并且由于表更新后,与该表相关的查询缓存会失效,查询缓存也没用,因此低效是必然的。
方案二
既然一条条插入很慢,那我通过List一次性插入多个不就行了。
xml语句:
<insert id="batchInsert">
insert into
bigbiao
(`menu`, `operation`, `uri`, `msg`,`creator`)
values
<foreach collection="list" item="item" separator=",">
(#{item.menu},#{item.operation},#{item.uri},#{item.msg},#{item.creator})
</foreach>
</insert>
测试类:
@SpringBootTest
@RunWith(SpringRunner.class)
public class BigBiaoMapperTest { @Autowired
private BigBiaoMapper bigBiaoMapper; @Test
public void batchInsert() {
BigBiao bigBiao = new BigBiao()
.setMenu("批量添加2号")
.setOperation("batchAdd")
.setUri("/begin/batch/add/big/biao")
.setMsg("{\"method:Insert\",\"costTime:88\",\"ip:0.0.0.255\",\"添加一堆东西\"}")
.setCreator("LonZyuan");
List<BigBiao> bigBiaos = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
bigBiaos.add(bigBiao);
}
bigBiaoMapper.batchInsert(bigBiaos);
long end = System.currentTimeMillis();
System.out.println("执行时间:" + (end - start) + "ms");
} }
运行,查看执行时间:

速度很快,那我现在插10w条进去:
@Test
public void batchInsert() {
BigBiao bigBiao = new BigBiao()
.setMenu("批量添加2号")
.setOperation("batchAdd")
.setUri("/begin/batch/add/big/biao")
.setMsg("{\"method:Insert\",\"costTime:88\",\"ip:0.0.0.255\",\"添加一堆东西\"}")
.setCreator("LonZyuan");
List<BigBiao> bigBiaos = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
bigBiaos.add(bigBiao);
}
bigBiaoMapper.batchInsert(bigBiaos);
long end = System.currentTimeMillis();
System.out.println("执行时间:" + (end - start) + "ms");
}
但是又翻车了:

查一下Packet for query is too large,原来MySQL会根据配置文件,限制Server接受数据包的大小,
图中(16500100 > 4194304)就是具体问题点,4194304 B = 4MB,所以是这个值小了。
解决:
这个参数为 max_allowed_packet ,在 ini 配置文件中设置一下:
max_allowed_packet = 20M
重启MySQL,然后再次运行:

10w条数据插入成功了
这里可能有小伙伴想问那我直接插1000w条进去,那就会发生OOM问题:

这个问题后续在做探讨。
MySQL插入大量数据探讨的更多相关文章
- mysql 插入/更新数据
mysql 插入/更新数据 INSERT 语句 1.一次性列出全部字段的值,例如: INSERT INTO student VALUES('Chenqi','M', 29); INSERT INTO ...
- [转载]mysql插入大量数据
mysql的批量数据格式, 比如 INSERT INTO TABLES (LABLE1,LABLE2,LABLE3,...) VALUES(NUM11,NUM12,NUM13,...), (NUM ...
- C API向MySQL插入批量数据的快速方法——关于mysql_autocommit
MySQL默认的数据提交操作模式是自动提交模式(autocommit).这就表示除非显式地开始一个事务,否则每个查询都被当做一个单独的事务自动执行.我们可以通过设置autocommit的值改变是否是自 ...
- MySQL插入中文数据出现?号
原文转载自:https://blog.csdn.net/LynneZoe/article/details/79174119 运行环境:win10 mysql版本:Mysql5.6 做一个项目的时候,向 ...
- mysql插入中文数据变成问号怎么处理
插入中文数据变成问号,一般都是因为字符集没有设置成utf8的原因 1.修改字符集: ALTER TABLE 表名 MODIFY 列名 类型(50) CHARACTER SET "utf8&q ...
- laravel 解决mysql插入相同数据的问题
1.背景: 每天0点定时任务统计数据,实现目标是统计时如果没有今天的统计数据,那就执行insert操作 如果存在那就执行update操作: 代码逻辑 1 if(报表存在){ 2 update(); 3 ...
- mysql插入表数据中文乱码问题解决方案
一.问题 开发中遇到将其它数据库数据插入到mysql数据库表中一直会报类似如下错误: Incorrect string value: '\xE6\x88\x91' for column 'name' ...
- MySQL插入大批量数据时报错“The total number of locks exceeds the lock table size”的解决办法
事情的原因是:我执行了一个load into语句的SQL将一个很大的文件导入到我的MySQL数据库中,执行了一段时间后报错"The total number of locks exceeds ...
- MySQL 插入 中文数据乱码解决
问题描述: 1.在命令行中进行插入,没有问题.但是显示存在部分乱码 2.在JDBC中插入成功.中文是直接以“??”形式显示. 通过Navicat客户端查看 与在网页中看到的一一致,说明读取没有问题,问 ...
随机推荐
- 按照工业标准1英寸=25.4mm,而在电子元件成像领域Sensor尺寸1英寸=16mm。
按照工业标准1英寸=25.4mm,而在电子元件成像领域Sensor尺寸1英寸=16mm. 我们平常所说的CCD/CMOS的尺寸,实际上是指Sensor对角线的长度,这一点跟我们平常所说的屏幕尺寸是一样 ...
- NorFlash、NandFlash在技术和应用上有些什么区别?
首先你要搞懂什么是Flash Memory? Flash Memory(快闪存储器),是一种电子式可清除程序化只读存储器的形式,允许在操作中被多次擦或写的存储器.这种科技主要用于一般性数据存储,以及在 ...
- RocketMQ源码详解 | Broker篇 · 其一:线程模型与接收链路
概述 在上一节 RocketMQ源码详解 | Producer篇 · 其二:消息组成.发送链路 中,我们终于将消息发送出了 Producer,在短暂的 tcp 握手后,很快它就会进入目的 Broker ...
- Spring中自定义Schema扩展机制
一.前言 Spring 为基于 XML 构建的应用提供了一种扩展机制,用于定义和配置 Bean. 它允许使用者编写自定义的 XML bean 解析器,并将解析器本身以及最终定义的 Bean 集成到 S ...
- 转载:10G以太网光口与Aurora接口回环实验
10G以太网光口与高速串行接口的使用越来越普遍,本文拟通过一个简单的回环实验,来说明在常见的接口调试中需要注意的事项.各种Xilinx FPGA接口学习的秘诀:Example Design.欢迎探讨. ...
- Bzoj通过5题纪念
我A了五题啦!!!
- Swift-技巧(二)模糊脸部功能
摘要 本文介绍模糊脸部的功能逻辑和实现方式,实现方式会尽可能的使用苹果提供的 API,保证功能高效率和简洁. 逻辑 模糊脸部的逻辑主要有两个流程,就是先找到脸部,然后模糊脸部,那么就引申出这两个实现问 ...
- jquery 实现 <imput>标签 密码框显示/隐藏密码功能
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 < ...
- dart系列之:dart语言中的异常
目录 简介 Exception和Error Throw和catch Finally 总结 简介 Exception是程序中的异常情况,在JAVA中exception有checked Exception ...
- 在Winform中直接录入表格数据和在Vue&Elment中直接录入表格数据的比较
一般来说,录入数据的时候,我们都采用在一个窗体界面中,根据不同内容进行录入,但是有时候涉及主从表的数据录入,从表的数据有时候为了录入方便,也会通过表格控件直接录入.在Winform开发的时候,我们很多 ...