关掉 unique 约束能明显提速,因 mysql 逐行校验 unique 索引开销大,设 unique_checks=0 可延迟至导入后一次性校验,前提是数据无重复。

为什么关掉 UNIQUE 约束能明显提速?
MySQL 在插入每行时,都会检查所有 UNIQUE 索引(包括主键)是否冲突。对千万级数据逐行校验,I/O 和 CPU 开销会指数级上升。关掉它不是跳过约束,而是把校验延迟到导入完成后再一次性做——前提是确认数据本身无冲突。
实操建议:
- 导入前执行
SET UNIQUE_CHECKS = 0;导入后立即设回1 - 仅对当前会话生效,不影响其他连接
- 如果表有多个
UNIQUE索引,该设置一并关闭全部,无需逐个操作 - 注意:若数据实际存在重复,后续设回
1时会报错,需先用SELECT检查去重
innodb_flush_log_at_trx_commit=2 和 =0 怎么选?
这个参数控制 InnoDB 日志刷盘频率。=1(默认)最安全但最慢;=2 折中:日志写入 OS 缓存即返回,崩溃可能丢 1 秒事务;=0 最快但风险最高,崩溃可能丢最多 1 秒数据且无法保证事务原子性。
实操建议:
- 大批量导入场景下,优先设为
2,兼顾速度与基本可靠性 - 设为
0仅适用于临时库、测试环境或可接受数据丢失的离线处理 - 修改方式:
SET GLOBAL innodb_flush_log_at_trx_commit = 2(需 SUPER 权限) - 导入完成后务必恢复原值,避免影响线上事务一致性
用 LOAD DATA INFILE 替代 INSERT 批量语句
LOAD DATA INFILE 是 MySQL 原生导入命令,绕过 SQL 解析层,直接解析文本进存储引擎,比拼接千条 INSERT 快 5–20 倍。但权限和路径限制多,容易卡在第一步。
常见错误现象:
-
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option:说明服务端限制了可读目录 -
File 'xxx.csv' not found:路径是相对于 MySQL 服务端,不是客户端
实操建议:
- 先查允许路径:
SHOW VARIABLES LIKE 'secure_file_priv' - 把文件放到返回路径下,再用绝对路径调用,例如:
LOAD DATA INFILE '/var/lib/mysql-files/data.csv' INTO TABLE t1 - 加
LOCAL关键字(LOAD DATA LOCAL INFILE)可读客户端文件,但需服务端开启local_infile=ON且客户端驱动支持 - 配合
FIELDS TERMINATED BY ','和LINES TERMINATED BY '\n'显式声明格式,避免隐式转换出错
索引重建时机比想象中更关键
很多人以为“先删索引 → 导入 → 再建索引”一定最快,其实未必。InnoDB 的二级索引构建,在数据已排序(如按主键顺序导入)时,可以批量合并页,效率远高于边插边更新索引树。但若原始数据乱序,删除索引反而让最终建索引阶段更慢。
实操建议:
- 如果源数据按主键/聚簇索引顺序排列(比如导出自另一个 InnoDB 表),保留主键,只删非唯一二级索引
- 如果数据完全随机,可考虑先删所有非主键索引,导入完再用
ALTER TABLE ... ADD INDEX重建——但必须确保重建时没有并发写入 - 重建索引期间表可读不可写,大表操作建议在低峰期进行
- 不要用
DROP INDEX+CREATE INDEX分两步,ALTER TABLE一条命令更高效
真正卡住效率的,往往不是单个开关,而是多个设置之间的相互影响——比如关了 UNIQUE_CHECKS 却没调 innodb_buffer_pool_size,缓冲池太小会导致频繁刷脏页,反而拖慢整体进度。这些参数得一起看,不能只改一个就以为万事大吉。











