请求协助编写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




