笔者想进行数据库查询优化探索,但是前提是需要一个很大的表,因此得先导入大量数据至一张表中。

准备工作

准备一张表,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插入大量数据探讨的更多相关文章

  1. mysql 插入/更新数据

    mysql 插入/更新数据 INSERT 语句 1.一次性列出全部字段的值,例如: INSERT INTO student VALUES('Chenqi','M', 29); INSERT INTO ...

  2. [转载]mysql插入大量数据

    mysql的批量数据格式, 比如 INSERT INTO TABLES (LABLE1,LABLE2,LABLE3,...)  VALUES(NUM11,NUM12,NUM13,...),  (NUM ...

  3. C API向MySQL插入批量数据的快速方法——关于mysql_autocommit

    MySQL默认的数据提交操作模式是自动提交模式(autocommit).这就表示除非显式地开始一个事务,否则每个查询都被当做一个单独的事务自动执行.我们可以通过设置autocommit的值改变是否是自 ...

  4. MySQL插入中文数据出现?号

    原文转载自:https://blog.csdn.net/LynneZoe/article/details/79174119 运行环境:win10 mysql版本:Mysql5.6 做一个项目的时候,向 ...

  5. mysql插入中文数据变成问号怎么处理

    插入中文数据变成问号,一般都是因为字符集没有设置成utf8的原因 1.修改字符集: ALTER TABLE 表名 MODIFY 列名 类型(50) CHARACTER SET "utf8&q ...

  6. laravel 解决mysql插入相同数据的问题

    1.背景: 每天0点定时任务统计数据,实现目标是统计时如果没有今天的统计数据,那就执行insert操作 如果存在那就执行update操作: 代码逻辑 1 if(报表存在){ 2 update(); 3 ...

  7. mysql插入表数据中文乱码问题解决方案

    一.问题 开发中遇到将其它数据库数据插入到mysql数据库表中一直会报类似如下错误: Incorrect string value: '\xE6\x88\x91' for column 'name' ...

  8. MySQL插入大批量数据时报错“The total number of locks exceeds the lock table size”的解决办法

    事情的原因是:我执行了一个load into语句的SQL将一个很大的文件导入到我的MySQL数据库中,执行了一段时间后报错"The total number of locks exceeds ...

  9. MySQL 插入 中文数据乱码解决

    问题描述: 1.在命令行中进行插入,没有问题.但是显示存在部分乱码 2.在JDBC中插入成功.中文是直接以“??”形式显示. 通过Navicat客户端查看 与在网页中看到的一一致,说明读取没有问题,问 ...

随机推荐

  1. stm32驱动超声波模块

    下面是关于stm32驱动超声波模块的一段代码,有需要的朋友可以复制参考,希望对大家能够有所帮助和启发. #define HCSR04_PORT GPIOB #define HCSR04_CLK RCC ...

  2. C/C++中浮点数输出精度的问题

    本文使用C++语言书写,对于C的小伙伴们,如果编译不通过的话--就说明C里面没有这个内容,可以跳过 通常来说,我们书写程序主要只用整形变量 (signed/unsigned) (long/long l ...

  3. 并发编程从零开始(十二)-Lock与Condition

    并发编程从零开始(十二)-Lock与Condition 8 Lock与Condition 8.1 互斥锁 8.1.1 锁的可重入性 "可重入锁"是指当一个线程调用 object.l ...

  4. Ubuntu virtualenv 创建 python2 虚拟环境 激活 退出

    首先默认安装了virtualenv 创建python2虚拟环境 your-name@node-name:~/virtual_env$ virtualenv -p /usr/bin/python2 py ...

  5. v3

    #include <iostream> #include <time.h> #include "map" #include "stdio.h&qu ...

  6. Spring Cloud Alibaba 使用RestTemplate进行服务消费

    创建服务提供者工程 创建spring-cloud-alibaba-service-member工程,会员中心服务该服务提供用户会员信息. pom.xml <?xml version=" ...

  7. 让 AI 为你写代码 - 体验 Github Copilot

    前几天在群里看到有大神分享 Copoilot AI 写代码,看了几个截图有点不敢相信自己的眼睛.今天赶紧自己也来体验一下 Copoilot AI 写代码到底有多神奇. 申请 现在 Copoilot 还 ...

  8. 大白话讲解如何解决HttpServletRequest的请求参数只能读取一次的问题

    大家在开发过程中,可能会遇到对请求参数做下处理的场景,比如读取上送的参数中看调用方上送的系统编号是否是白名单里面的(更多的会用request中获取IP地址判断).需要对请求方上送的参数进行大小写转换或 ...

  9. building sasl.wrapper extention

    yum install gcc-c++ python-devel.x86_64 cyrus-sasl-devel.x86_64 pip install pyhs2 ref: https://www.o ...

  10. IO流(一)

    内容概要: Java以流的形式处理所有输入和输出.流是随通信路径从源移动到目的地的字节序列. 内存与存储设备之间传输数据的通道 流的分类: 按方向 输入流:将存储空间中的内容读到内存中   硬盘--& ...