MySQL快速插入百万行测试数据

MySQL快速插入百万行测试数据

整体思路:

  • 1、如何产生大量数据?
    可以利用循环,重复制造大量数据
  • 2、如何快速将数据存储(插入)数据表?
    直接使用循环也可以做到,但是速度可能会相对慢一点。可以利用MYSQL MEMORY引擎,加速数据的插入。
-- 1、创建内存表
-- 使用MEMORY数据库引擎,创建内存表。
-- 将数据直接插入内存表,再将数据从内存表复制到普通表,效率优于直接插入普通表
CREATE TABLE `table_in_memory` (
  `id` INT(6) NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `name` VARCHAR(50) NOT NULL COMMENT '名称',
  `pwd` VARCHAR(32) NOT NULL COMMENT '密码',
  `create_time` DATETIME DEFAULT NULL COMMENT '创建日期',
  PRIMARY KEY (`id`)
) ENGINE=MEMORY AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COMMENT='内存临时表';


-- 2、创建使用MYISAM引擎的普通表,存放最终数据的表
-- 针对大量测试数据的这个场景,可以不考虑事务,因此可以使用MYISAM引擎
CREATE TABLE `test_data` (
  `id` INT(6) NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `name` VARCHAR(50) NOT NULL COMMENT '名称',
  `pwd` VARCHAR(32) NOT NULL COMMENT '密码',
  `create_time` DATETIME DEFAULT NULL COMMENT '创建日期',
  PRIMARY KEY (`id`)
) ENGINE=MYISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COMMENT='测试数据表';

-- 3、创建一个函数,用于生成随机数据
-- 尽管是测试数据,但是100W行一模一样的数据也就没有什么测试业务的价值。在创建测试数据的时候,使用一些算法,
-- 将数据尽量模拟真实一点。
DROP FUNCTION IF EXISTS rand_string;
DELIMITER $$
CREATE FUNCTION rand_string(n INT)
RETURNS VARCHAR(255)
BEGIN
    DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    DECLARE return_str VARCHAR(255) DEFAULT '';
    DECLARE i INT DEFAULT 0;
    WHILE i < n DO
        SET return_str = CONCAT(return_str,SUBSTRING(chars_str , FLOOR(1 + RAND()*62 ),1));
        SET i = i +1;
    END WHILE;
    RETURN return_str;
END $$
DELIMITER ;



-- 4、创建存储过程,批量调用函数,生成大量随机数,并插入临时表(内存表)
DROP PROCEDURE IF EXISTS `add_data`;
DELIMITER $$
CREATE PROCEDURE `add_data`(IN n INT)
BEGIN
    DECLARE i INT UNSIGNED DEFAULT 0;
    WHILE i < n DO
        INSERT INTO `table_in_memory`(NAME,pwd,create_time) 
        VALUES (rand_string(15),MD5(123456),NOW());
        SET i = i+1;
    END WHILE;
END $$
DELIMITER ;

-- 5、调用存储过程,调用之前最好先看一下,自己表最大存储量是多少,如果容量太少会导致,表爆满而插入失败。
-- 执行100W次的数据生成和插入。
-- 这里的时间依赖上面步骤中生成随机数的算法的效率,如果生成随机数的算法比较复杂,在100W次的执行中,
-- 也会比较耗时。另外和机器性能也有关。本机使用以上相对简单的随机数算法,执行了3次,平均1min 10sec左右
-- 完成100W行数据生成并插入内存表 
CALL add_data(1000000);

-- 6、将内存表中的数据插入到普通表中
INSERT into test_data SELECT * from  table_in_memory;

调用存储过程之前最好先看一下,自己表最大存储量是多少,如果容量太少会导致,表爆满而插入失败。

show variables like '%table_size'

将表容量改为1024M。在MYSQL安装路径下C:\ProgramData\MySQL\MySQL Server 8.0,找到my.ini配置文件,修改max_heap_table_size 参数的大小。如果不存在这个参数,直接添加

注意:ProgramData文件是隐藏的,要在查看中显示隐藏

max_heap_table_size = 1024M

MySQL快速插入百万行测试数据_第1张图片

重启数据库实例,让修改的配置生效。进入cmd 输入net stop mysql80 停掉服务,然后输入net start mysql80 启动服务

注意:MySQL8.0版本的要加80,不是8.0版本的不用,

MySQL快速插入百万行测试数据_第2张图片

重启后,查询show variables like '%table_size' 再次查看容量 。这是将表容量改为1024M后的显示

MySQL快速插入百万行测试数据_第3张图片

确定表容量够的话,再调用存储过程

CALL add_data(1000000);

遇到的问题

插入数据过慢,每秒插入几百条数据,插入一百万条数据耗时五十多分钟。正常每秒应该插入几千条数据(随机数算法,MD5算法比较耗时。如果没有用到这些算法更快,每秒一两万都可以)。

问题分析

MySQL8 默认是开启了bin_log日志,在执行插入的时候会保存日志比较耗时,另外有索引的话还要维护索引插入也会比较耗时。这里我们没用用到索引(如果有索引先关闭索引,插入后在开启索引就好了),所以我们直接关闭日志就好了 。

bin_log会一致保存,不会删除,导致占用大量的磁盘空间,在没有必要的情况下,可以禁用 bin_log 日志

1.首先我们查看一下bin_log 日志状态

show variables like 'log_%';

MySQL快速插入百万行测试数据_第4张图片

NO表示开启,OFF表示关闭。这里我已经关了,所以是OFF

  1. 关闭bin_log日志

    找到MySQL的配置文件 my.ini文件,我的在C:\ProgramData\MySQL\MySQL Server 8.0\my.ini。注意(ProgramData是隐藏文件,要先在查看中打开隐藏才可以看到)

    #添加一下任何一个即可
    skip-log-bin
    disable-log-bin
    
  2. 修改了my.ini文件后,重启mysql服务。再次查看bin_log 日志状态:show variables like 'log_%';bin_log 日志就关闭了image-20210925231042392

在次插入十万条数据,只需要一分钟就好了。

补充:随机数算法,MD5算法比较耗时。下面是没用哪些算法,插入十万条数据只需要5秒钟就好了。

MySQL快速插入百万行测试数据_第5张图片

你可能感兴趣的:(MySQL,mysql,数据库,sql)