You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

请求协助编写MySQL脚本生成4000万条employees表模拟数据

生成4000万条employees表模拟数据的高效MySQL方案

直接单条插入4000万数据绝对会慢到让人崩溃,咱们得用批量插入+存储过程的组合拳,再配合一些性能优化操作,才能高效完成这个任务。下面是一步步的实操方案:

一、前期性能优化配置

先调整MySQL的核心参数,临时禁用索引和约束,能大幅降低插入时的性能开销:

-- 关闭自动提交,减少事务日志的频繁写入
SET autocommit = 0;
-- 临时禁用唯一索引和普通索引(插入完成后再恢复)
ALTER TABLE employees DISABLE KEYS;
-- 调大允许的数据包大小,避免批量插入时触发溢出报错
SET max_allowed_packet = 1073741824; -- 1GB

二、创建生成随机数据的存储过程

这个存储过程每次批量插入1000条数据,循环40000次就能凑齐4000万条。里面包含了随机名字、生日、入职日期的逻辑,尽量贴近真实业务数据:

DELIMITER //

CREATE PROCEDURE generate_employees()
BEGIN
    DECLARE v_emp_no INT DEFAULT 1;
    DECLARE v_loop_count INT DEFAULT 0;
    -- 准备常用的中英文名字池,随机选取更真实
    DECLARE first_names VARCHAR(2000) DEFAULT 'John,Michael,David,Emily,Hannah,Ashley,张伟,李娜,王强,刘芳';
    DECLARE last_names VARCHAR(2000) DEFAULT 'Smith,Johnson,Williams,Brown,张伟,李娜,王强,刘芳,陈杰,赵婷';
    
    WHILE v_loop_count < 40000 DO -- 40000 * 1000 = 4000万
        START TRANSACTION;
        INSERT INTO employees (emp_no, birth_date, first_name, last_name, gender, hire_date)
        SELECT
            v_emp_no + seq,
            -- 生成1950-01-01到1990-12-31之间的随机生日
            DATE_ADD('1950-01-01', INTERVAL FLOOR(RAND() * 14609) DAY),
            -- 从名字池随机选取名字
            SUBSTRING_INDEX(SUBSTRING_INDEX(first_names, ',', FLOOR(RAND() * 10) + 1), ',', -1),
            SUBSTRING_INDEX(SUBSTRING_INDEX(last_names, ',', FLOOR(RAND() * 10) + 1), ',', -1),
            -- 随机生成性别
            IF(RAND() > 0.5, 'M', 'F'),
            -- 入职日期设置在生日满18年后,且不晚于2023-12-31
            DATE_ADD(
                DATE_ADD('1950-01-01', INTERVAL FLOOR(RAND() * 14609) DAY),
                INTERVAL FLOOR(18 + RAND() * 40) YEAR
            )
        FROM
            (SELECT 0 seq UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
             SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t1,
            (SELECT 0 seq UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
             SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2,
            (SELECT 0 seq UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
             SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t3; -- 10*10*10=1000条批量插入
        
        SET v_emp_no = v_emp_no + 1000;
        SET v_loop_count = v_loop_count + 1;
        COMMIT;
    END WHILE;
END //

DELIMITER ;

三、执行存储过程生成数据

运行下面的命令启动数据生成,这个过程耗时取决于你的服务器配置(CPU、内存、磁盘IO),耐心等一会儿就行:

CALL generate_employees();

四、恢复数据库配置

数据全部插入完成后,记得把索引和自动提交恢复回来,保证后续业务的正常运行:

-- 重新启用索引,重建索引结构
ALTER TABLE employees ENABLE KEYS;
-- 开启自动提交,回到默认事务模式
SET autocommit = 1;

额外小贴士

  • 如果服务器内存有限,可以把批量插入的数量调小(比如改成500条),避免内存溢出。
  • 名字池可以根据需求扩展,比如添加更多中英文名字,让模拟数据更贴近真实场景。
  • 要是希望emp_no自动递增,可以先把表结构里的emp_no设置为INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,这样存储过程里就不用手动维护v_emp_no变量了。

内容的提问来源于stack exchange,提问作者J. Doe

火山引擎 最新活动