zoukankan      html  css  js  c++  java
  • MySQL 快速创建千万级测试数据

    创建基础表结构

    不管用何种方式,我要插在那张表总要创建的吧

    CREATE TABLE `t_user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `c_user_id` varchar(36) NOT NULL DEFAULT '',
      `c_name` varchar(22) NOT NULL DEFAULT '',
      `c_province_id` int(11) NOT NULL,
      `c_city_id` int(11) NOT NULL,
      `create_time` datetime NOT NULL,
      PRIMARY KEY (`id`),
      KEY `idx_user_id` (`c_user_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

     

    方式1:采用存储过程和内存表

    创建内存表

    利用 MySQL 内存表插入速度快的特点,我们先利用函数和存储过程在内存表中生成数据,然后再从内存表插入普通表中

    CREATE TABLE `t_user_memory` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `c_user_id` varchar(36) NOT NULL DEFAULT '',
      `c_name` varchar(22) NOT NULL DEFAULT '',
      `c_province_id` int(11) NOT NULL,
      `c_city_id` int(11) NOT NULL,
      `create_time` datetime NOT NULL,
      PRIMARY KEY (`id`),
      KEY `idx_user_id` (`c_user_id`)
    ) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4;

     创建函数和存储过程

    # 创建随机字符串和随机时间的函数
    mysql> delimiter $$
    mysql> CREATE DEFINER=`root`@`%` FUNCTION `randStr`(n INT) RETURNS varchar(255) CHARSET utf8mb4
        ->     DETERMINISTIC
        -> 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$$
    Query OK, 0 rows affected (0.00 sec)

    mysql> CREATE DEFINER=`root`@`%` FUNCTION `randDataTime`(sd DATETIME,ed DATETIME) RETURNS datetime
        ->     DETERMINISTIC
        -> BEGIN
        ->     DECLARE sub INT DEFAULT 0;
        ->     DECLARE ret DATETIME;
        ->     SET sub = ABS(UNIX_TIMESTAMP(ed)-UNIX_TIMESTAMP(sd));
        ->     SET ret = DATE_ADD(sd,INTERVAL FLOOR(1+RAND()*(sub-1)) SECOND);
        ->     RETURN ret;
        -> END $$

    mysql> delimiter ;

    # 创建插入数据存储过程
    mysql> CREATE DEFINER=`root`@`%` PROCEDURE `add_t_user_memory`(IN n int)
        -> BEGIN
        ->     DECLARE i INT DEFAULT 1;
        ->     WHILE (i <= n) DO
        ->         INSERT INTO t_user_memory (c_user_id, c_name, c_province_id,c_city_id, create_time) VALUES (uuid(), randStr(20), FLOOR(RAND() * 1000), FLOOR(RAND() * 100), NOW());
        ->         SET i = i + 1;
        ->     END WHILE;
        -> END
        -> $$
    Query OK, 0 rows affected (0.01 sec)

    调用存储过程

    mysql> CALL add_t_user_memory(1000000);
    ERROR 1114 (HY000): The table 't_user_memory' is full

    出现内存已满时,修改 max_heap_table_size 参数的大小,我使用64M内存,插入了22W数据,看情况改,不过这个值不要太大,默认32M或者64M就好,生产环境不要乱尝试

    从内存表插入普通表

    mysql> INSERT INTO t_user SELECT * FROM t_user_memory;
    Query OK, 218953 rows affected (1.70 sec)
    Records: 218953  Duplicates: 0  Warnings: 0

    方式2:采用临时表

    创建临时数据表tmp_table

    CREATE TABLE tmp_table (
        id INT,
        PRIMARY KEY (id)
    );

    用 python或者bash 生成 100w 记录的数据文件(python瞬间就会生成完)

    python(推荐):python -c "for i in range(1, 1+1000000): print(i)" > base.txt

    导入数据到临时表tmp_table中

    mysql> load data infile '/Users/LJTjintao/temp/base.txt' replace into table tmp_table;
    Query OK, 1000000 rows affected (2.55 sec)
    Records: 1000000  Deleted: 0  Skipped: 0  Warnings: 0

    千万级数据 20秒插入完成

    注意:导入数据时有可能会报错,原因是mysql默认没有开secure_file_priv( 这个参数用来限制数据导入和导出操作的效果,例如执行LOAD DATA、SELECT … INTO OUTFILE语句和LOAD_FILE()函数。这些操作需要用户具有FILE权限。)

    解决办法:在mysql的配置文件中(my.ini 或者 my.conf)中添加 secure_file_priv = /Users/LJTjintao/temp/`, 然后重启mysql 解决

     

     以临时表为基础数据,插入数据到t_user中,100W数据插入需要10.37s

    INSERT INTO t_user
        ->   SELECT
        ->     id,
        ->     uuid(),
        ->     CONCAT('userNickName', id),
        ->     FLOOR(Rand() * 1000),
        ->     FLOOR(Rand() * 100),
        ->     NOW()
        ->   FROM
        ->     tmp_table;
    Query OK, 1000000 rows affected (10.37 sec)
    Records: 1000000  Duplicates: 0  Warnings: 0

    更新创建时间字段让插入的数据的创建时间更加随机

    UPDATE t_user SET create_time=date_add(create_time, interval FLOOR(1 + (RAND() * 7)) year);

    Query OK, 1000000 rows affected (5.21 sec)
    Rows matched: 1000000  Changed: 1000000  Warnings: 0

    mysql> UPDATE t_user SET create_time=date_add(create_time, interval FLOOR(1 + (RAND() * 7)) year);


    Query OK, 1000000 rows affected (4.77 sec)
    Rows matched: 1000000  Changed: 1000000  Warnings: 0

    学而不思则罔,思而不学则殆
  • 相关阅读:
    WC命令
    dcoker machine
    linux命令
    Valgrind 检测程序内存使用
    golang flag
    面试之---二叉树的遍历
    FFMpeg 版本错误
    C++中namespace的使用
    QT之QStatusBar
    建立ftp服务器和客户端
  • 原文地址:https://www.cnblogs.com/linyu51/p/15014187.html
Copyright © 2011-2022 走看看