MySQL 通过存储过程高效插入100w条数据

news2024/11/29 11:52:55

目录

    • 一、前言
    • 二、创建表
    • 三、编写存储过程插入数据
    • 四、高效插入数据方案
      • 4.1、插入数据时删除表中全部索引
      • 4.2、存储过程中使用统一事务插入(性能显著提升)
      • 4.3、调整MySQL系统配置(性能显著提升,适合存储过程没有使用统一事务)
        • 查看MySQL这两个配置默认值(一般默认都是1)
        • 修改MySQL配置文件
        • 插入10w数据测试
    • 五、总结

一、前言

最近在做SQL索引优化的时候经常需要批量插入一些数据,采用存储过程来进行批量插入是一个很好的选择,但是在插入100w数据时我本地耗时需要24分钟有点顶不住,本文会讲解如何通过存储过程批量插入数据,并且提供两个提升插入速度的方法。

二、创建表

DROP TABLE IF EXISTS `order_info`;
CREATE TABLE `order_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单ID',
  `order_no` varchar(100) NOT NULL COMMENT '订单编号',
  `customer_id` bigint(20) NOT NULL COMMENT '客户编号',
  `goods_id` bigint(20) NOT NULL COMMENT '商品ID',
  `goods_title` varchar(100) COLLATE utf8mb4_0900_as_cs DEFAULT NULL COMMENT '商品标题',
  `order_status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '订单状态 1:待支付 2:已支付 3:已发货 4、已收货',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_as_cs COMMENT='订单信息表';

三、编写存储过程插入数据

在测试的时候插入数据量可以调小一点,一次别插入太多,如果存储过程不加事务插入10w条数据我本地耗时143秒,插入100w数据我本地耗时24分钟太慢了,可以先看下面高效插入数据方案

## 创建一个插入数据的存储过程
DROP PROCEDURE IF EXISTS insert_procedure;
delimiter;;
CREATE PROCEDURE insert_procedure () 
BEGIN
  # 定义循环值
  DECLARE i INT DEFAULT 1;
  # 开启事务
  START TRANSACTION;
  # 开始循环插入
  WHILE ( i <= 1000000 ) DO
    INSERT INTO `order_info`(`order_no`,`customer_id`, `goods_id`, `goods_title`, `order_status`, `create_time`) VALUES (CONCAT('ON00000',i), CEIL(RAND() * 100), CEIL(RAND() * 100), CONCAT('笔记本电脑',i), MOD(i, 4)+1, NOW());
    SET i = i + 1;
  END WHILE;
END;;
delimiter;

# 调用存储过程插入数据
CALL insert_procedure ();

四、高效插入数据方案

MySQL版本:8.0.18

如果MySQL不做任何配置,我本地固态盘使用MySQL8.0插入10w条数据耗时142s,插入数据量越大可能等比耗时更长,一般表中都会创建一些索引,在插入数据的时候也会变更索引,尤其是唯一索引会增长插入数据的时间,要想加快插入速度有多种方法,硬件上的优化就不说了,这里只说三个方法够我们做SQL索引优化测试即可。

4.1、插入数据时删除表中全部索引

将表中索引全部删除,包括主键索引,尤其是自增主键索引还有唯一索引,自己生成ID保证自增不重复即可,这里以10w条数据做测试对比,插入100w数据耗时太长。

我本地10w条数据插入有自增主键索引插入耗时142s,删除主键索引改用自己生成ID值插入耗时139s,这个数据量还比较小,有兴趣可以加大数据量测试,数据量越大差值越明显。

只需要把把存储过程中的SQL改一下把让 ID 使用 i 的值即可

INSERT INTO `order_info`(id,`order_no`,`customer_id`, `goods_id`, `goods_title`, `order_status`, `create_time`) VALUES (i, CONCAT('ON00000',i), CEIL(RAND() * 100), CEIL(RAND() * 100), CONCAT('笔记本电脑',i), MOD(i, 4)+1, NOW());

4.2、存储过程中使用统一事务插入(性能显著提升)

在存储过程中添加事务,存储过程中的每次新增语句都会开启一个自己的事务,控制所有新增都在一个事务中,10w条数据插入耗时从142s提升到20s,速度大大提升,但是有个问题这20s其它插入操作需要等待,线上业务需要考量一下,本地SQL索引优化测试倒是一个很不错的选择。

  • 给存储过程添加上统一事务
## 创建一个插入数据的存储过程
DROP PROCEDURE IF EXISTS insert_procedure;
delimiter;;
CREATE PROCEDURE insert_procedure () 
BEGIN
  # 定义循环值
  DECLARE i INT DEFAULT 1;
  #定义一个错误的变量,类型是整形,默认是0
  DECLARE t_error INTEGER DEFAULT 0;
  #捕获到sql的错误,就设置t_error为1
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1;
  # 开启事务
  START TRANSACTION;
  # 开始循环插入
  WHILE ( i <= 1000000 ) DO
    INSERT INTO `order_info`(`order_no`,`customer_id`, `goods_id`, `goods_title`, `order_status`, `create_time`) VALUES (CONCAT('ON00000',i), CEIL(RAND() * 100), CEIL(RAND() * 100), CONCAT('笔记本电脑',i), MOD(i, 4)+1, NOW());
    SET i = i + 1;
  END WHILE;

  #如果捕获到错误
  IF t_error=1 THEN
    #回滚
    ROLLBACK;
  ELSE
    #提交
    COMMIT;
  END IF;
END;;
delimiter;

# 调用存储过程插入数据
CALL insert_procedure ();

4.3、调整MySQL系统配置(性能显著提升,适合存储过程没有使用统一事务)

这种方案是适合存储过程没有使用统一事务插入,每一次插入都需要开启事务然后提交,对存储过程中使用了统一事务插入提升不大。

MySQL有两个配置是控制日志文件写入的,在计算器中最耗时的操作就是IO,MySQL默认是会同步写入redo日志和binlog日志的,我们插入100w数据就需要同步写入100w次redo日志和100w次binlog日志,这是非常耗时的,如果能改成异步批量写入则可以大大加快新增数据的速度,但是可能会导致数据库宕机时数据丢失问题,这里不做详细说明。

  • innodb_flush_log_at_trx_commit (控制redo日志写入模式)
    • 等于0: log buffer每秒就会被刷写日志文件到磁盘,提交事务的时候不做任何操作(执行是由mysql的master thread线程来执行的。
    • 等于1: 每次提交事务的时候,都会将log buffer刷写到日志 (默认)
    • 等于2: 表示在每次事务提交的时候会把log buffer刷到文件系统中去,但并不会立即刷写到磁盘。如果只是MySQL数据库挂掉了,由于文件系统没有问题,那么对应的事务数据并没有丢失。只有在数据库所在的主机操作系统损坏或者突然掉电的情况下,数据库的事务数据可能丢失1秒之类的事务数据。这样的好处,减少了事务数据丢失的概率,而对底层硬件的IO要求也没有那么高(log buffer写到文件系统中,一般只是从log buffer的内存转移的文件系统的内存缓存中,对底层IO没有压力)。
  • sync_binlog (控制binlog日志写入模式)
    • 在提交n次事务后,进行binlog的落盘,0为不进行强行的刷新操作,而是由文件系统控制刷新日志文件,如果是在线交易和账有关的数据建议设置成1,如果是其他数据可以保持为0即可
查看MySQL这两个配置默认值(一般默认都是1)
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
SHOW VARIABLES LIKE 'sync_binlog';

在这里插入图片描述

修改MySQL配置文件

我的MySQL是Linux版的配置文件在/etc/mysql/my.cnf,window 上的 MySQL 配置文件默认是在 C:\Program Files\MySQL\MySQL Server 8.0\my-default.ini。

# 打开/etc/mysql/my.cnf
vi /etc/mysql/my.cnf
  • 在配置文件中的[mysqld]下添加如下配置
## 2表示在每次事务提交的时候会把log buffer刷到文件系统中去,但并不会立即刷写到磁盘。
innodb_flush_log_at_trx_commit = 2
## 0为不进行强行的刷新操作,而是由文件系统控制刷新日志文件
sync_binlog = 0
  • 重启MySQL
service mysqld restart
# 或 
service mysql restart
插入10w数据测试
  • 修改前
    -

  • 修改后
    在这里插入图片描述
    插入速度还是比使用统一事务插入差很多。

五、总结

我的需求是为了做SQL索引优化测试需要批量插入一些数据,这里最适合我的是4.2中添加统一事务来插入方案。

  • 4.2方案存储过程中使用统一事务,插入100w数据耗时217秒差不多3.6分钟,没有调整前耗时24分钟插入速度提升6.6倍多。
  • 4.3方案调整MySQL配置,插入100w数据耗时415秒差不多7分钟,没有调整前耗时24分钟插入速度提升3.4倍多。

要想高效插入数据还有很多种方法,我这里只是为了做SQL索引优化测试使用,这个插入耗时我还可以接受,有其它好的方法可以一起交流。

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

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

相关文章

云计算安全:保护你的数据免受黑客侵害

文章目录 云计算的崛起云计算安全的挑战1. 数据隐私2. 身份认证和访问控制3. 网络安全4. 云供应商安全 云计算安全的最佳实践1. 数据加密2. 强身份认证3. 访问控制4. 安全审计5. 更新和漏洞管理6. 培训和教育 云计算安全的未来1. 量子安全性2. 人工智能和机器学习3. 边缘计算安…

邮戳锁StampedLock

一、是什么 二、邮戳锁由锁饥饿问题引出 StampedLock类的乐观读锁闪亮登场&#xff0c;通过版本号控制 三、邮戳锁特点与缺点 StampedLock不可重入

26947-2011 手动托盘搬运车 学习记录

声明 本文是学习GB-T 26947-2011 手动托盘搬运车. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了手动托盘搬运车(以下简称托盘车)的结构参数、技术要求、试验方法、检验规则、 标志、包装、运输和贮存。 本标准适用于额定载荷…

数据仓库与数据挖掘(1)概述

一、数据仓库和数据挖掘概述 1.1 数据仓库的产生 数据仓库与数据挖掘&#xff1a; 数据仓库和联机分析处理技术(存储)。数据挖掘&#xff1a;在大量的数据中心挖掘感兴趣的知识、规则、规律、模式、约束(分析)。数据仓库用于决策分析&#xff1a; 数据仓库&#xff1a;是在数…

毛玻璃态登录表单

效果展示 页面结构组成 通过上述的效果展示可以看出如下几个效果 底部背景有三个色块并且效果是毛玻璃效果登录表单是毛玻璃效果登录表单的周围的小方块也是有毛玻璃效果并且与登录表单有层次效果 CSS3 知识点 filter 属性backdrop-filter 属性绝对定位属性动画属性 底部背…

CISSP学习笔记:密码学与对称加密算法

第六章 密码学与对称加密算法 6.1 密码学历史上的里程碑 6.1.1 凯撒密码 简单的将字母表中的每个字母替换成其后的三个字母&#xff0c;是单一字母的替代置换密码 6.1.2 美国内战 美国内战使用词汇替代和置换的复杂组合&#xff0c;从而试图破坏敌人的破译企图 6.1.3 Ult…

MySQL 用户权限和远程访问设置

目录 一、用户操作查看当前拥有用户创建用户修改用户密码删除用户给root用户开放外网访问 二、用户权限操作授予权限的原则查看授予用户的权限给用户添加权限回收权限 一、用户操作 先要使用root用户登录MySQL后在执行后面操作 查看当前拥有用户 SELECT host,user,Grant_pri…

结构型设计模式——外观模式

摘要 本文主要分析设计模式 - 结构型 - 外观(Facade)&#xff0c;它提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口&#xff0c;从而让子系统更容易使用。 一、外观模式的意图 提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口&#xff0c;从而让…

记录 ubuntu 修改用户/root 密码步骤

1、普通用户修改密码方法 a&#xff09;启动 Ubuntu&#xff0c;随即长按 shift 进入 grub 菜单 b&#xff09;选择 Advanced options for ubuntu&#xff0c;即高级设置 c&#xff09;选择 recovery mode&#xff0c;回车确认,如下图&#xff1b; d&#xff09;在 Recovery…

力扣用队列实现栈

自己写的栈&#xff0c;再让其他函数去调用自己写的栈 typedef int QDataType; typedef struct QueueNode {struct QueueNode* next;//单链表QDataType data;//放数据 }QNode;typedef struct Queue {QNode* phead;//头节点QNode* ptail;//尾节点QDataType size; //统计有多少节…

使用Qt验证RGB格式

下面我们用不同的颜色来绘制一块矩形区域&#xff0c;来对比学习RGB颜色。 一片漆黑的黑色 黑色在RGB中是三个颜色分量都是0。也就是没有颜色。 下面我们绘制一个水平100个像素&#xff0c;垂直200个像素的矩形区域&#xff0c;颜色设置为黑色。 #ifndef MAINWINDOW_H #def…

【NLP的python库(03/4) 】: 全面概述

一、说明 Python 对自然语言处理库有丰富的支持。从文本处理、标记化文本并确定其引理开始&#xff0c;到句法分析、解析文本并分配句法角色&#xff0c;再到语义处理&#xff0c;例如识别命名实体、情感分析和文档分类&#xff0c;一切都由至少一个库提供。那么&#xff0c;你…

【小笔记】从算法训练现象分析可能的参数设置问题-loss分析篇

【学而不思则罔&#xff0c;思而不学则殆】 9.30 首先给出一个理想的训练loss收敛图片&#xff1a;loss平滑的下降&#xff0c;并逐渐收敛到0. 平滑说明学习率设置较合适&#xff0c;收敛到0说明模型在参数空间中收敛到一个很理想的区域。 1.训练集的loss已经开始收敛了&…

Spring Boot的自动装配中的@ConditionalOnBean条件装配注解在Spring启动过程中,是如何保证处理顺序靠后的

前言 为什么Spring Boot条件注解那么多&#xff0c;而标题中是ConditionalOnBean呢&#xff1f; 因为&#xff0c;相比之下我们用的比较多的条件装配注解也就是ConditionalOnClass、ConditionalOnBean了&#xff0c;而ConditionalOnClass对顺序并不敏感&#xff08;说白了就是判…

蓝牙智能音箱采用哪些音频功放芯片

目前&#xff0c;无线蓝牙智能音箱越来越受广大用户的欢迎&#xff1b;比如点播歌曲、上网购物&#xff0c;或是了解天气预报&#xff0c;它也可以对智能家居设备进行控制&#xff0c;比如打开窗帘、设置冰箱温度、提前让热水器升温等。 而功放芯片是音箱中至关重要的组成部分…

分布式事务-TCC案例分析流程图

防止cancel方法在最后执行出现问题&#xff0c;用户收到提示已经退款成功但是由于cancel过慢或者出现问题&#xff08;虽然最后会重试成功但是用户体验很差&#xff09;&#xff0c;可以做以下的业务sql模型优化(增加一个冻结金额)。

Arcgis克里金插值报错:ERROR 010079: 无法估算半变异函数。 执行(Kriging)失败。

Arcgis克里金插值报错&#xff1a;ERROR 010079: 无法估算半变异函数。 执行(Kriging)失败。 问题描述&#xff1a; 原因&#xff1a; shape文件的问题&#xff0c;此图可以看出&#xff0c;待插值的点有好几个都超出了地理范围之外&#xff0c;这个不知道是坐标系配准的问…

Tensorflow2 GPU 安装方法

一、Tensorflow2 GPU 安装方法 1. 首先安装Anaconda3环境2. 在Anaconda Prompt 中安装tensorflow23. 验证GPU是否可以使用 1. 首先安装Anaconda3环境 https://www.anaconda.com/ 2. 在Anaconda Prompt 中安装tensorflow2 conda update conda conda create -n tensorflow pyt…

基于Java的社区管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言功能介绍&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导…

【算法导论】快速排序

文章目录 1. 快速排序的描述 1.1基本描述1.2 PARTITOION函数1.3 快速排序C完整代码 2. 快速排序的性能2.1 最坏时间复杂度2.2 平均时间复杂度 1. 快速排序的描述 1.1基本描述 快速排序是一种时间复杂度为 O(n^2) 的排序算法。虽然最坏情况时间复杂度很差&#xff0c;但他的平…