单条INSERT变批量VALUES、autocommit=0+显式COMMIT、LOAD DATA INFILE是三大提速手段;分别解决SQL解析开销、事务刷盘惩罚和IO路径冗长问题,配合分段提交与参数调优可覆盖80%慢插入场景。

单条INSERT变批量VALUES:最直接的提速手段
MySQL默认每执行一条INSERT就走一次完整SQL生命周期:网络传输、语法解析、事务开启、redo写入、binlog刷盘。10万条数据 = 10万次开销。把它们合并成一条语句,能砍掉90%以上的非写入耗时。
常见错误是盲目拼接上万条VALUES——触发max_allowed_packet限制(默认4MB),报错Packets larger than max_allowed_packet are not allowed;或导致SQL解析卡顿。
- 单条
INSERT ... VALUES建议控制在1000~2000行,约1~2MB大小 - 字段含大文本(如
TEXT、JSON)时,行数要更保守,优先压到500行以内 - 用
CONCAT或程序拼接时,注意SQL注入风险,必须参数化处理
autocommit=0 + 显式COMMIT:绕过默认事务惩罚
MySQL默认autocommit=1,意味着每条INSERT都是独立事务,强制刷redo log和binlog。这是批量插入慢的隐形元凶。
手动关掉自动提交后,1000条插入只产生1次日志刷盘,性能提升立竿见影。但别忘了COMMIT,否则连接断开时事务回滚,数据全丢。
- 执行前先
SET autocommit = 0,插入完再COMMIT - 不要用
START TRANSACTION包裹——它会加全局锁,反而拖慢并发写入 - 如果中途出错,需
ROLLBACK,否则后续INSERT会因事务残留失败
LOAD DATA INFILE比INSERT快10倍以上:百万级数据的首选
当数据量超过10万行,硬拼INSERT语句已不是最优解。LOAD DATA INFILE跳过SQL解析层,直接读文件、构造行、写页,IO路径极短。
但它要求文件在数据库服务器本地(或启用了local_infile=ON),且格式严格。常见报错Can't get stat of ... (Errcode: 2)就是路径不对或权限不足。
- CSV文件必须用
LINES TERMINATED BY '\n',Windows换行符\r\n会导致最后一列错位 - 字段含逗号或引号时,必须用
FIELDS ENCLOSED BY '"'包裹,否则解析失败 -
LOAD DATA不走binlog(除非sql_log_bin=1),主从同步需额外确认
innodb_flush_log_at_trx_commit=0:牺牲一点持久性换速度
生产环境慎用,但迁移/导入场景下值得考虑。设为0后,事务提交不再强制刷redo log到磁盘,而是依赖每秒一次的后台刷盘,吞吐量飙升。
代价是崩溃时可能丢失最多1秒数据。如果导入中途MySQL挂了,最后一批没刷盘的数据就没了——所以务必配合COMMIT分段,比如每5000行提交一次。
- 临时生效:
SET GLOBAL innodb_flush_log_at_trx_commit = 0 - 恢复安全值:
SET GLOBAL innodb_flush_log_at_trx_commit = 1 - 别在my.cnf里永久改这个值,除非你清楚所有业务对数据持久性的容忍度
LOAD DATA,别硬扛。



















