load data infile 比批量 insert 快几十倍,根本原因是其在 mysql 服务端直接解析文件并写入存储引擎,绕过 sql 解析、权限校验、网络往返及逐条事务日志刷盘;而批量 insert 仍需走完整 sql 生命周期,受限于 max_allowed_packet 和 innodb_log_buffer_size 等参数。

为什么 LOAD DATA INFILE 比批量 INSERT 快几十倍
根本原因在于执行层级不同:LOAD DATA INFILE 是 MySQL 服务端直接读文件解析并写入存储引擎,绕过了 SQL 解析、权限校验、网络往返(本地导入时)、事务日志逐条刷盘等开销;而 INSERT 即使是批量形式(如 INSERT INTO t VALUES (),(),()),仍需走完整 SQL 生命周期,每批仍受 max_allowed_packet 和 innodb_log_buffer_size 等限制。
实测对比:1000 万行 CSV(约 1.2GB)导入 InnoDB 表,LOAD DATA INFILE 耗时约 90 秒;同等配置下用 1000 行/批的 INSERT(禁用 autocommit + 手动事务包裹)耗时约 2800 秒——差距超 30 倍。
- MySQL 默认对
LOAD DATA INFILE做了大量底层优化,比如行缓冲合并、索引延迟更新(配合DISABLE KEYS)、页预分配 -
INSERT的瓶颈常卡在 redo log 刷盘频率和唯一索引实时校验上,无法规避 - 网络导入(
LOAD DATA LOCAL INFILE)会额外增加客户端解析和传输开销,性能下降明显,应优先用服务端本地文件
必须设置的 MySQL 配置项和权限
不配好这些,LOAD DATA INFILE 直接报错或静默失败。
- 服务端参数
secure_file_priv必须指定目录(如/var/lib/mysql-files/),且文件必须放在此路径下;设为NULL则完全禁用该功能 - 用户需有
FILE权限:GRANT FILE ON *.* TO 'your_user'@'%'; - 导入目标表最好提前关闭唯一键检查:
ALTER TABLE t DISABLE KEYS;,导入完成再ENABLE KEYS;(仅对 MyISAM 有效;InnoDB 无效,但可关掉唯一约束校验来提速) - InnoDB 场景下更关键的是调大
innodb_buffer_pool_size(建议 ≥ 数据大小的 50%)和innodb_log_file_size(避免频繁 checkpoint)
LOAD DATA INFILE 实际命令的关键参数取舍
字段分隔、行结束、空值处理稍有偏差就会整批导入失败或数据错位,不能靠“大概像”。
LOAD DATA INFILE '/var/lib/mysql-files/data.csv' INTO TABLE my_table FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS SET created_at = STR_TO_DATE(@created_at, '%Y-%m-%d %H:%i:%s');
-
FIELDS TERMINATED BY和LINES TERMINATED BY必须与文件真实换行符严格一致;Windows 文件用'\r\n',Linux 用'\n',Mac 旧格式可能用'\r' -
ENCLOSED BY用于包裹含逗号或换行的字段,若 CSV 无引号,此项必须省略或设为空(ENCLOSED BY ''),否则首尾引号会被当内容导入 -
IGNORE 1 ROWS跳过标题行,但只跳物理行,不校验列数是否匹配 - 时间/数字类型转换强烈建议用
SET子句配合函数(如STR_TO_DATE、NULLIF),别依赖隐式转换——隐式转换失败会导致整行被置为默认值或截断
常见失败现象和对应解法
错误信息往往很短,但原因分散,需要结合日志和文件抽样定位。
-
ERROR 13 (HY000): Can't get stat of '/path/to/file' (Errcode: 13 - Permission denied):不是 MySQL 用户没权限,而是 mysqld 进程用户(如 mysql)对文件路径无读权限;用sudo -u mysql ls -l /path/to/file验证 -
ERROR 1262 (01000): Row 1 was truncated; it contained more data than there were input columns:字段数对不上,常见于某行多了一个未转义的引号、或ENCLOSED BY设置错误导致解析崩坏;用head -n 5 data.csv | cat -A查看不可见字符 - 导入后数值全为 0 或日期变 0000-00-00:源文件字段顺序与
INSERT列顺序不一致,且未显式指定列名;务必写成LOAD DATA ... INTO TABLE t (col1,col2,...) - 导入速度突然暴跌(如前 100 万行快,后面越来越慢):通常是唯一索引或外键触发了逐行校验;确认是否误开了
FOREIGN_KEY_CHECKS=1或UNIQUE_CHECKS=1,临时关掉:SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0;
千万级导入不是“丢个命令就去喝咖啡”,关键路径上的每个环节都得验证——文件权限、字段边界、字符集(确保 character_set_filesystem 和表字符集一致)、以及最后用 SELECT COUNT(*) 和 CHECKSUM TABLE 对比源文件行数和校验和。











