电脑生活派
柔彩主题三 · 更轻盈的阅读体验

批量插入怎么优化?这几个实用技巧让你的数据库飞起来

发布时间:2025-12-12 04:50:29 阅读:242 次

做后台开发或者数据分析时,经常要往数据里塞大量数据。比如每天导入几万条订单记录、用户行为日志,或者从 Excel 批量同步客户信息。如果一条一条 insert,等得花儿都谢了。这时候就得靠批量插入来提速。但光是用了批量插入还不够,写法不对照样慢。

别用单条 Insert 拼接字符串

有些人图省事,把多条 insert 语句拼成一个长字符串发给数据库,像这样:

INSERT INTO users (name, age) VALUES ('张三', 25);
INSERT INTO users (name, age) VALUES ('李四', 30);
INSERT INTO users (name, age) VALUES ('王五', 28);

这种写法虽然一次提交,但数据库还是要逐条解析执行,IO 和解析开销一点没少,效率提升有限。

用多值 Insert 才是正道

真正高效的写法是把多个值合并到一条 SQL 中:

INSERT INTO users (name, age) VALUES 
('张三', 25),
('李四', 30),
('王五', 28),
('赵六', 33);

这样数据库只需要解析一次 SQL,然后批量处理所有值,性能能提升好几倍。实测插入 10000 条数据,从几十秒降到几秒。

控制每批数据量

别一口气插 10 万条。数据包太大会被 MySQL 截断,报错 “Packet too large”。可以通过设置 max_allowed_packet 调整上限,但更稳妥的做法是分批提交,比如每批 500~1000 条。

写个循环,每次组装 500 条数据发出去,既稳定又高效。

关闭自动提交,手动控制事务

默认情况下,每条 SQL 都会自动提交事务,频繁写磁盘自然慢。应该先关掉自动提交,把一批 insert 包在同一个事务里:

START TRANSACTION;
INSERT INTO users (name, age) VALUES (...), (...), (...);
INSERT INTO users (name, age) VALUES (...), (...);
COMMIT;

这样整个批次只做一次磁盘刷写,速度明显提升。注意别让事务太大,避免锁表太久影响其他操作。

临时禁用索引和外键检查(仅限初始

如果是首次导入大量历史数据,可以考虑临时关掉非主键索引和外键约束:

ALTER TABLE users DISABLE KEYS; -- 仅 MyISAM
-- 或对于 InnoDB,可临时删掉二级索引

导入完成后再重建索引。这个方法风险高,只适合离线初始化场景,日常业务中千万别乱用。

使用 LOAD DATA INFILE 处理大文件

如果数据来自 CSV 文件,直接用 MySQL 的 LOAD DATA INFILE 命令:

LOAD DATA INFILE '/tmp/users.csv'
INTO TABLE users
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(name, age);

这几乎是最快的导入方式,底层做了高度优化,比任何程序代码都快。前提是文件得在数据库服务器上,或者开启 local_infile=1 支持本地上传。

程序端优化:别在循环里发请求

用 Python 写脚本时常见错误:

for row in data:
    cursor.execute("INSERT INTO users VALUES (%s, %s)", row)

这等于发了 N 次网络请求。正确做法是用 executemany

cursor.executemany(
    "INSERT INTO users (name, age) VALUES (%s, %s)",
    [(‘张三’, 25), (‘李四’, 30), ...]
)

驱动会自动帮你拼成多值 insert 或使用批量协议,效率天差地别。

不同数据库有不同招

PostgreSQL 推荐用 COPY 命令;SQL Server 有 BULK INSERT;Oracle 可以上数组绑定(Array Binding)。工具选对,事半功倍。

批量插入不是简单堆数量,而是从 SQL 写法、事务控制、程序调用到数据库配置全链路优化。实际项目中组合使用这些方法,轻松应对万级甚至百万级数据导入。