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客户端查看 与在网页中看到的一一致,说明读取没有问题,问 ...
随机推荐
- Noip模拟37 2021.8.12
T1 数列 真是考场上不是数学的乱推柿子,想定理,是数学的没想出来.. 比较悲伤... 列柿子不用动脑子,就是没有想出来$EXgcd$解不定方程,淦.. 解处一组解后利用比较显然的性质: $x+\fr ...
- 2021.8.16考试总结[NOIP模拟41]
T1 你相信引力吗 肯定是单调栈维护.但存在重复值,还是个环,不好搞. 发现取区间时不会越过最大值,因此以最大值为断点将环断为序列.在栈里维护当前栈中有多少个与当前元素相等的元素,小分类讨论一下. 最 ...
- MVC之三个单选按钮的切换选择
实现需求: 1.三个多选按钮中:只能同时选择限时抢购和分享金或者拼团特惠和分享金,其中限时抢购和拼团特惠不能同时选择.并且点击后显示,再次点击赢隐藏. 1 @*活动信息*@ 2 <div> ...
- Swarm+Docker+Portainer(集群,图形化)
参考文章 https://blog.csdn.net/u011781521/article/details/80469804 https://blog.csdn.net/u011781521/arti ...
- vim 脚本,自动添加文件头部信息
相信很多人编写脚本的时候都会在脚本头部写一些信息,记录文件生成时候,生成人姓名等 建议在自己的家目录下的 .vimrc 文件 下添加以下内容 [ autocmd BufNewFile *.sh exe ...
- EF Core 小技巧:迁移已经应用到数据库,如何进行迁移回退操作?
场景描述:项目中存在两个迁移 Teacher 和 TeachingPlan ,TeachingPlan 在 Teacher 之后创建,并且已经执行 dotnet ef database update ...
- 将python代码转化为c语言代码,提高运行效率
将python代码转化为c语言代码,提高运行效率 首先,需要安装cpython库: pip install cython 安装完成之后,写一段简单的代码,例如下面这个利用递归求斐波那契数列的函数,然后 ...
- js--数组的 Array.of() 和 Array.from() 方法的使用总结
前言 JavaScript 中数组的本质是一个对象,它存在的 length 属性值随数组元素的长度变化,但是开发中经常会遇到拥有 length 属性和若干索引属性的对象,被称为类数组对象,类数组对象和 ...
- java中的lamda表达式
List操作: 循环: list.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getL ...
- IDEA安装热部署插件JRebel
首先说下热部署是什么意思吧,简单了说就是在我们对代码进行更改之后,不需要重启项目,重新编译一下就可以直接运行最新的代码的部署方式.既然是部署方式,项目启动部署的时候当然就会和正常情况下不一样啦~ JR ...