LOAD DATA INFILE 比 INSERT 快十倍以上,因其绕过 SQL 解析、单行事务开销和网络往返;而 INSERT 需走完整查询生命周期且默认每行自动提交。

LOAD DATA INFILE 为什么比 INSERT 快十倍以上
因为 LOAD DATA INFILE 是 MySQL 原生批量导入机制,绕过了 SQL 解析、单行事务开销和网络往返;而逐条 INSERT 每次都要走完整查询生命周期,还默认在 autocommit 模式下每行提交一次事务。
实操建议:
- 确保数据文件是纯文本(如 CSV),字段分隔符统一(常用
\t或,),无 BOM 头 - 目标表最好提前建好,且关闭唯一索引和外键检查:
SET unique_checks=0; SET foreign_key_checks=0; - 导入后记得恢复:
SET unique_checks=1; SET foreign_key_checks=1;,否则后续插入可能出错 - 如果用的是 MyISAM 引擎,还能加
DISABLE KEYS,导入完再ENABLE KEYS,进一步跳过索引维护
本地文件无法加载?检查 secure_file_priv 和 LOCAL 关键字
常见错误现象:ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement —— 这说明 MySQL 只允许从特定目录读取文件。
实操建议:
- 先查限制路径:
SHOW VARIABLES LIKE 'secure_file_priv';,把数据文件放到该路径下才能用LOAD DATA INFILE - 如果必须从客户端本地读(比如你用 mysql 客户端连远程库),改用
LOAD DATA LOCAL INFILE,但服务端和客户端都得开启支持:local_infile=ON - MySQL 8.0+ 默认禁用
LOCAL,启动客户端时要加--local-infile=1,否则会静默失败或报错ERROR 1148
字段映射错位、NULL 和空字符串混了怎么办
CSV 字段数不匹配、时间格式不对、数字里夹空格,都会导致整行被跳过(默认不报错),只在 warning 里提示,非常隐蔽。
实操建议:
- 导入前用
SHOW WARNINGS;看有没有Warning | 1265 | Data truncated for column ...类提示 - 强制指定字段名,避免靠位置猜错:
LOAD DATA INFILE '/path/data.csv' INTO TABLE t1 (col1, col2, @var3) SET col3 = NULLIF(@var3, '') - 日期字段别依赖自动转换,用
STR_TO_DATE()显式解析:SET created_at = STR_TO_DATE(@date_str, '%Y-%m-%d %H:%i:%s') - 数值字段含逗号或货币符号?先用
REPLACE()清洗:SET price = REPLACE(@price_str, ',', '')
千万级数据导入卡住或内存爆掉?调这几个参数
默认配置下,LOAD DATA 会尝试一次性缓存整块数据,遇到超大文件容易 OOM 或锁表太久。
实操建议:
- 拆分大文件:用
split -l 100000 data.csv chunk_分成 10 万行/份,逐个导入,更可控 - 调大缓冲区(仅对
INFILE有效):SET SESSION read_buffer_size = 1024*1024*8;(8MB),但别设太高,影响并发 - 控制事务粒度:MyISAM 不用管;InnoDB 下可手动分批,比如每 10 万行
COMMIT一次(需在脚本里实现,原生命令不支持) - 注意磁盘 IO:SSD 上快很多,机械盘建议关掉
innodb_flush_log_at_trx_commit(临时设为 2),导入完再改回来
最容易被忽略的是字段类型定义和实际数据的隐式转换行为——比如 VARCHAR(10) 存了 12 个字符的字符串,MySQL 可能截断不报错,等你查数据时才发现丢了内容。


















