asyncpg和aiomysql等异步驱动本身不解决大批量insert慢的问题,慢的根源在于sql执行方式而非协程调度;必须避免循环调用execute(),改用executemany()批量接口、控制每批1000–5000行并分事务提交,配合合理连接池配置才能实现高效写入。

asyncpg 和 aiomysql 等异步驱动本身不解决大批量 INSERT 慢的问题——慢的根源在 SQL 执行方式,不是协程调度。
别用 execute() 循环插入
这是最常见也最致命的写法:await conn.execute("INSERT ...", row) 在循环里调用 N 次。每条语句都触发一次网络往返 + 参数序列化 + 事务日志写入,性能是 O(N),10 万行可能耗时数十秒。
- 即使用了
async,也只是“并发地慢”,不是“快” - 连接池再大也扛不住高频小包请求,反而加剧连接争抢
- PostgreSQL 的
INSERT ... VALUES (...), (...)多值语法、MySQL 的executemany都被绕过了
改用 executemany() 或原生批量接口
异步驱动基本都支持真正的批量执行,关键是要一次性传入全部参数,而不是拆成单条。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
-
asyncpg:用conn.executemany("INSERT INTO t (a,b) VALUES ($1,$2)", data),data是元组列表,比单条快 5–10 倍 -
aiomysql:同理,await cursor.executemany(...),注意它默认不自动提交,需显式await conn.commit() - 超大规模(百万+):直接走
conn.copy_records_to_table()(PostgreSQL)或生成 CSV 后调用LOAD DATA(MySQL),跳过 SQL 解析层
控制事务边界和批大小
全量包在一个事务里,可能锁表太久、内存爆掉;每行一事务,又回到原点。折中方案是分批提交。
- 每 1000–5000 行为一批,
await conn.executemany()+await conn.execute("COMMIT") - 避免在循环里调
conn.transaction()—— 它会新建事务对象,开销不小;直接用COMMIT字符串更轻量 - PostgreSQL 下可考虑
SAVEPOINT实现失败回滚局部批次,但多数场景直接重试整批更简单
连接池配置必须匹配写入强度
异步写入密集时,连接池不是越大越好,而是要防止“连接饥饿”和“连接雪崩”。
-
min_size设为 2–4,保证常驻连接不频繁重建 -
max_size建议设为 CPU 核数 × 2~4(如 8 核配 16),超过后新请求排队,比超发更可控 - 禁用
pool_recycle,改用pool_pre_ping=True,避免空闲连接失效导致首次查询超时 - 检查实际活跃连接:
SELECT count(*) FROM pg_stat_activity WHERE state = 'active';,如果长期接近max_size,说明批大小太小或并发太高
await 关键字,而是你有没有让数据库一次吞下足够多的数据。批量接口、合理分批、连接复用,这三件事做扎实了,异步写入才能跑出真实吞吐。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










