单条INSERT多VALUES是最易上手的提速方式,将1000行数据合并为一条语句可比单行插入快5–10倍,核心是减少999次网络往返、SQL解析和事务提交开销。

单条 INSERT 多 VALUES 是最易上手的提速方式
直接把 1000 行数据塞进一条 INSERT INTO ... VALUES (...), (...), (...) 里,比循环执行 1000 次单行 INSERT 快 5–10 倍。这不是玄学,而是省掉了 999 次网络往返、SQL 解析和事务提交开销。
实操时注意三点:
- 每批控制在
1000–2000行,单语句体积别超1–2MB;否则可能触发max_allowed_packet限制(默认 4MB,可查SHOW VARIABLES LIKE 'max_allowed_packet') - 必须显式写出列名,比如
INSERT INTO t (a, b, c) VALUES (...),避免表结构变更后字段错位 - 如果用 JDBC,记得开启 rewriteBatchedStatements=true(MySQL Connector/J 参数),它会自动把多条
addBatch()合并成一个VALUES语句发给服务端
手动事务 + 关闭 autocommit 才能释放批量写入潜力
即使用了多 VALUES,若每条语句仍走默认 autocommit=1,那每次执行完还是立刻刷一次 redo log——等于盖了 1000 次章。真正要提速,得把这批插入包进一个事务里。
做法很简单:
- 执行
SET autocommit = 0或代码里调用connection.setAutoCommit(false) - 拼好一批
INSERT语句(比如 1000 条),一次性执行 - 执行
COMMIT,此时才统一刷盘 - 切记:
COMMIT后要立即SET autocommit = 1或重置连接状态,否则后续语句会意外滞留在未提交事务中
LOAD DATA INFILE 是百万级插入的终极方案
当数据已存在本地文件(如 CSV),LOAD DATA INFILE 的速度通常是 INSERT 的 5–20 倍。它绕过 SQL 解析层,直接由 MySQL 服务端读文件、解析、写入,I/O 和 CPU 利用率都更高效。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
但有几个硬性前提和坑:
- 文件必须在数据库服务器本地(或启用
local_infile=1并用LOAD DATA LOCAL INFILE,但需客户端和服务端同时允许) - 目标表不能有太多二级索引——建议先
DROP INDEX,导入完成再重建,否则索引维护会吃掉大半性能 - 字段分隔符、行结束符要对齐,比如
FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n',否则容易跳行或截断 - 遇到脏数据(如类型不匹配)默认会中断整个导入,加
IGNORE可跳过错误行,但得提前确认业务是否允许丢数据
INSERT ... SELECT 适合跨表迁移场景
如果你的数据源本身就是另一张 MySQL 表(比如从日志备份表往主表灌数),INSERT INTO t1 SELECT ... FROM t2 WHERE ... 是最优解。它完全在服务端内存中流转,不经过网络传输,也不生成客户端侧的中间结果集。
关键点在于:
- 确保
t2上的WHERE条件能命中索引,否则全表扫描会拖慢整个过程 - 避免在
SELECT中用函数或子查询做复杂计算,这些都会在每一行上重复执行 - 如果
t1有自增主键且t2没提供值,MySQL 会正常分配;但若t2提供了主键值,需确认是否启用了innodb_autoinc_lock_mode=2(8.0 默认),否则可能因锁竞争卡住
实际跑百万级插入时,最容易被忽略的是“索引与约束的临时让步”——不是所有索引都值得在导入期间保留,也不是所有外键检查都非做不可。关掉它们,导入完再开,往往比调优 SQL 本身更能换来数量级提升。










