LOAD DATA INFILE 比 INSERT 快十倍以上,但需服务端启用 --local-infile=1、客户端显式开启 local_infile=True,并严格处理 CSV 格式、字符集、索引及引擎差异。

LOAD DATA INFILE 比 INSERT 快十倍以上,但默认被禁用
MySQL 默认关闭 LOAD DATA INFILE,因为涉及文件系统读取权限问题。不先开这个,再快的语法也执行不了。
常见错误现象:ERROR 1148 (42000): The used command is not allowed with this MySQL configuration
- 服务端需在启动时加
--local-infile=1,或在配置文件my.cnf的[mysqld]和[client]段都加上local_infile = ON - 连接客户端时必须显式启用:用
mysql --local-infile=1 -u root -p,否则即使服务端开了也没用 - 如果用 Python 的
pymysql或mysql-connector-python,要传参local_infile=True,否则会静默忽略LOAD DATA LOCAL INFILE
CSV 文件格式不对,LOAD DATA 会静默截断或错位
字段分隔符、换行符、引号嵌套处理不到位,是导入后数据“看起来像对了,其实全乱了”的主因。
- 务必指定
FIELDS TERMINATED BY ','和LINES TERMINATED BY '\n',Windows 生成的 CSV 可能用\r\n,得写成LINES TERMINATED BY '\r\n' - 含逗号、换行、双引号的字段必须用双引号包裹,且内部双引号要写成两个:
"abc""def",否则LOAD DATA会提前切分行 - 首行是表头?加
IGNORE 1 ROWS;但注意它只跳过第一行,不校验列数是否匹配 - 字符集不一致会导致中文变问号,显式加
CHARACTER SET utf8mb4,尤其源文件是 Excel 另存为 CSV 时,默认可能是 GBK
INSERT INTO ... VALUES (...),(...),(...) 批量插入有临界点
单条 INSERT 插一万行比 LOAD DATA 慢几十倍;但拼成一条带 5000 个值的 INSERT,性能接近 LOAD DATA 的 70% —— 关键在批量大小和事务控制。
- 每条语句不要超过 1MB,MySQL 默认
max_allowed_packet=4M,超了直接报错Packets larger than max_allowed_packet are not allowed - 关掉自动提交:
SET autocommit = 0;,所有INSERT包在BEGIN; ... COMMIT;里,否则每条都刷盘 - 避免在循环里逐条
INSERT;用程序拼接时,按 1000–5000 行/批组装,太多易 OOM,太少事务开销占比高 - 目标表有索引?导入前用
ALTER TABLE tbl DISABLE KEYS;,导完再ENABLE KEYS;,能省掉大部分索引维护成本
MyISAM 和 InnoDB 的批量导入策略完全不同
引擎选错,再优化 SQL 也白搭。MyISAM 适合纯写入场景,InnoDB 要兼顾一致性,导入逻辑必须区分对待。
- MyISAM:支持
CONCURRENT INSERT,但仅限尾部追加;若表有空洞(删过数据),并发插入会锁表 —— 导入前先OPTIMIZE TABLE - InnoDB:
innodb_buffer_pool_size至少设为物理内存的 50%~75%,否则大量刷脏页拖慢速度;innodb_log_file_size太小会导致频繁 checkpoint - InnoDB 不支持
DISABLE KEYS,但可临时调低innodb_flush_log_at_trx_commit = 2(牺牲极端断电安全性换速度),导完立刻改回 1 - 如果表有外键或触发器,导入前
SET FOREIGN_KEY_CHECKS = 0;和SET SQL_LOG_BIN = 0;(仅从库慎用)
真正卡住的地方往往不是语法,而是权限配置、字符集隐式转换、缓冲区大小这些看不见的设置。调一次 SHOW VARIABLES LIKE '%buffer%';,比重写三遍 INSERT 有用得多。


















