大批量insert卡顿主因是索引维护——每行插入需更新主键b+树、所有二级索引及日志;索引越多耗时越非线性增长,3个二级索引即等效4次b+树写入;优先删除非必要索引、控制插入顺序、调优事务与日志配置、禁用唯一性检查(可信数据)、改用load data infile可显著提速。

索引维护是大批量INSERT卡顿的主因——每插一行,MySQL都要更新主键B+树、所有二级索引、写redo log和binlog。索引越多,耗时越非线性增长;若有3个二级索引,插入1行实际等于执行4次B+树写入操作。
优先禁用非必要索引(最直接有效)
对InnoDB表,ALTER TABLE ... DISABLE KEYS无效,但可手动移除非关键索引:
- 导入前执行 DROP INDEX idx_unneeded ON table_name,只保留主键和业务强依赖的唯一索引
- 导入完成立即重建:CREATE INDEX idx_unneeded ON table_name(col)
- 避免在含唯一约束的字段上删索引,否则重复数据可能静默跳过或报错
- 若表有5个以上二级索引,此操作常带来2–5倍提速
控制插入顺序,减少页分裂
无序主键(如UUID、倒序时间戳)会导致聚簇索引频繁页分裂,拖慢写入速度:
- 确保 VALUES 中的主键值单调递增(例如按时间正序、自增ID自然顺序)
- 避免 INSERT SELECT 时未加 ORDER BY —— 即使源表有序,执行计划也可能打乱顺序
- 若无法调整数据顺序,可先导入到临时无主键表,再按主键排序后 INSERT INTO 目标表
配合事务与配置调优,放大索引优化效果
单靠删索引不够,需组合事务控制和日志策略:
- 关闭自动提交:SET autocommit = 0,用 START TRANSACTION + COMMIT 包裹每批500–2000行
- 临时降低日志刷盘压力:SET GLOBAL innodb_flush_log_at_trx_commit = 2(崩溃最多丢1秒数据)
- 若不依赖binlog做恢复,可设 SET GLOBAL sync_binlog = 0;否则改用 sync_binlog = 1000 折中
- 禁用唯一性检查加速(仅限可信数据):SET unique_checks = 0,导入完再设为1
替代方案:绕过SQL层,用LOAD DATA INFILE
当数据已存为CSV/TSV文件时,这是比任何INSERT优化都快的路径:
- LOAD DATA INFILE 不走SQL解析器,直接写入引擎,比等量INSERT快5–20倍
- 必须把文件放到 secure_file_priv 指定目录(查 SHOW VARIABLES LIKE 'secure_file_priv')
- 导入前同样建议删掉非必要索引,导入后再建
- 注意字段分隔符与行结束符匹配,否则会静默跳过错误行;先导出10行测试再全量执行











