真正提速的关键是删非主键索引、关闭外键和唯一性检查,因DISABLE KEYS对InnoDB无效;必须执行SET FOREIGN_KEY_CHECKS=0、SET UNIQUE_CHECKS=0、DROP INDEX,再LOAD DATA,最后重建索引。

MySQL 导入千万级数据,光用 LOAD DATA INFILE 不够快;真正提速的关键是:InnoDB 表必须删索引 + 关检查,而不是幻想 DISABLE KEYS 能起作用。
为什么 ALTER TABLE ... DISABLE KEYS 对 InnoDB 完全无效
很多人照着 MyISAM 的优化方案直接套用到 InnoDB 表上,执行 ALTER TABLE t1 DISABLE KEYS 后发现导入速度毫无变化——因为这个命令在 InnoDB 下是空操作,既不报错也不生效。
-
DISABLE KEYS/ENABLE KEYS是 MyISAM 特有的机制,InnoDB 根本不识别它 - 执行后查
SHOW PROCESSLIST或监控information_schema.INNODB_METRICS中的index_page_splits,会发现索引页仍在持续分裂,说明索引实时更新没停 - 误以为“已优化”反而耽误真正该做的动作:删非主键索引、关约束检查
InnoDB 表导入前必须做的三件事
对 InnoDB,想让 LOAD DATA INFILE 接近理论最快速度,这三步缺一不可,且顺序不能乱:
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
- 执行
SET FOREIGN_KEY_CHECKS = 0和SET UNIQUE_CHECKS = 0—— 否则每行都会触发唯一性校验和外键查找,而你刚删了索引,这些查找会退化成全表扫描 - 用
DROP INDEX idx_name ON t1删除所有非主键索引(主键不能删,但可临时DROP PRIMARY KEY再重建,仅当主键不是业务关键时谨慎考虑) - 提前用
SHOW CREATE TABLE t1备份建表语句,把索引定义单独记下来,别指望靠记忆重建
LOAD DATA LOCAL INFILE 的实际坑点与写法
本地文件导入最常用,但也最容易卡在权限和格式上:
- 服务端必须开启
local_infile=ON(SET GLOBAL local_infile = ON),且启动参数不能含--local-infile=0;客户端连接也要加--local-infile参数 - Windows 生成的 CSV 默认换行是
\r\n,若写成LINES TERMINATED BY '\n',最后一列会多出\r,导致字段错位 - 时间字段如
"2024-03-15 14:22:08"不能直插,得用SET created_at = STR_TO_DATE(@created_at, '%Y-%m-%d %H:%i:%s') - 遇到唯一冲突要跳过或覆盖,加
IGNORE或REPLACE关键字,例如:LOAD DATA LOCAL INFILE '/tmp/data.csv' IGNORE INTO TABLE t1
导入后重建索引的时机和代价
索引不是导完就立刻重建——顺序错了,后续查询可能因缺失索引而雪崩:
- 导入完成后,**立刻**执行
SET UNIQUE_CHECKS = 1和SET FOREIGN_KEY_CHECKS = 1,恢复约束检查 - 紧接着用备份好的 DDL 重建索引,例如:
CREATE INDEX idx_status ON t1(status);不要等业务查询跑慢了才想起来 - 重建索引本身耗时,但比边插边维护索引快得多;实测千万行下,删索引导入 + 重建,总耗时常不到边插边建的 1/3
- 如果表有多个二级索引,
CREATE INDEX是串行构建的,无法并行加速,所以索引数量要精简,别堆一堆低效索引
真正容易被忽略的是:DISABLE KEYS 的幻觉比没优化更危险——它让你误以为已做完所有事,却对 InnoDB 的真实行为一无所知。删索引、关检查、备定义、速导入、快重建,这五步闭环才是千万级导入不翻车的底线。

















