MySQL大批量插入首选LOAD DATA INFILE,比多值INSERT快5–20倍,需启用local_infile=1、客户端本地文件路径、严格匹配字段与行分隔符,跳过SQL解析直写存储引擎。

直接用单条 INSERT INTO ... VALUES (...) 插入几千行,性能会断崖式下跌;真正高效的大批量插入,必须绕过常规语句路径。
MySQL 用 LOAD DATA INFILE 替代 INSERT
当数据量达百万级以上,LOAD DATA INFILE 是 MySQL 原生最快的方式,比拼接多值 INSERT 快 5–20 倍。它跳过 SQL 解析层,直接由存储引擎读取文件内容。
- 必须确保服务端启用
local_infile=1(客户端连接时加--local-infile,服务端执行SET GLOBAL local_infile = 1) - 文件需位于客户端本地,且路径要能被 MySQL 客户端进程访问(不是服务端磁盘路径)
- 字段分隔符、行终止符要与文件实际格式严格一致,否则整批失败,错误提示极简(如
ERROR 1262: Row 1 was truncated) - 目标表主键或唯一索引列必须已存在且无冲突,否则中断——不支持
ON DUPLICATE KEY UPDATE,需提前清洗
SQL Server 优先选 BULK INSERT 或 SqlBulkCopy
BULK INSERT 是 SQL Server 最快的本地文件导入方式,但要求文件对 SQL Server 服务账户可见;SqlBulkCopy 更灵活,适合从 .NET 应用内存中推送数据。
-
BULK INSERT必须带TABLOCK提示,否则默认行锁导致并发争抢,速度暴跌 - 导入前建议临时切换数据库恢复模式:
ALTER DATABASE yourdb SET RECOVERY BULK_LOGGED,避免全量日志写入撑爆磁盘 -
SqlBulkCopy.BatchSize推荐设为 5000–10000,太大易 OOM 或触发事务日志满,太小则失去批量意义 - 列映射必须显式调用
ColumnMappings.Add("src","dst"),源字段顺序与目标表不一致时尤其关键
通用策略:事务控制 + 主键预排序 + 索引暂停
无论哪种数据库,绕不开这三个底层影响点:事务提交开销、B+树页分裂、索引维护成本。
- 手动包裹
START TRANSACTION/COMMIT(MySQL)或BEGIN TRAN/COMMIT(SQL Server),把几千行压进一次提交,别依赖自动提交 - 如果主键是自增 ID 或时间戳,确保数据按主键升序排列再插入——乱序插入会导致频繁页分裂,写放大严重
- 非必要索引(尤其是非聚集索引)和外键约束,可在导入前
DROP INDEX或DISABLE CONSTRAINT,导入完成后再重建 - PostgreSQL 用户注意:
COPY命令比INSERT快一个数量级,但只接受标准输入或服务端文件路径
最常被忽略的是「字段类型严格匹配」:CSV 导入时,哪怕一列多了一个空格或隐式 NULL,整批就会失败,而错误信息往往只报“批量加载失败”,不指明具体位置。务必先用小样本验证格式与 schema 兼容性,再跑全量。


















