直接循环execute()插入慢是因为每次隐式提交事务导致频繁刷盘wal/journal,磁盘i/o成瓶颈;提速关键在于显式控制事务边界,即begin...commit包裹多条insert,并合理配置pragma及分批executemany。

为什么直接循环 execute() 插入慢得明显?
因为每次 execute() 默认都隐式开启并提交一个事务,相当于每插 1 行就刷盘 1 次 WAL 或 journal。磁盘 I/O 成为瓶颈,尤其在机械硬盘或高延迟 SSD 上,1000 行可能耗时数秒。
真正提速的关键不是“批量”本身,而是**显式控制事务边界**——把多条 INSERT 包进单个 BEGIN...COMMIT 中,让 SQLite 只做一次日志刷写和一次页刷新。
常见错误:只用 executemany() 却不关自动提交,性能几乎没提升。
必须关闭 autocommit 并手动管理事务
SQLite 的 Connection 默认是 autocommit=False(注意:这容易被误解为“已关自动提交”,其实它只是启用 Python 的上下文管理器行为,仍会在每条 DML 后隐式提交)。真正要关的是底层自动提交模式。
- 正确做法:初始化连接时传
autocommit=True,再手动用BEGIN开启事务 - 或者保持默认
autocommit=False,但第一句必须是conn.execute("BEGIN") -
绝对不要依赖
conn.isolation_level=None以外的值来“关自动提交”——它只影响 Python 层对COMMIT的触发时机,不改变 SQLite 引擎行为
示例:
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
conn = sqlite3.connect("data.db")
conn.execute("BEGIN") # 显式开始事务
conn.executemany("INSERT INTO logs (ts, msg) VALUES (?, ?)", data_list)
conn.commit() # 一次性提交
executemany() 的参数限制与安全边界
executemany() 不是万能批处理器:它内部仍是一行行绑定并调用 C 层 sqlite3_bind_*,只是省去了 Python 循环开销。真正卡住的往往是数据量过大导致内存暴涨或 SQLite 的 SQLITE_MAX_VARIABLE_NUMBER 限制(默认 999)。
- 单次
executemany()最好不超过 500–800 行,避免触发变量数超限 - 如果
data_list有 5000 行,拆成 10 批,每批execute("BEGIN"); executemany(...); commit() - 别用
executescript()拼 SQL 字符串插入——无法参数化,SQL 注入风险高,且 SQLite 不优化多语句执行计划
错误示范:
# 危险!字符串拼接 + executescript
conn.executescript("INSERT INTO t VALUES (" + "),(".join(str(x) for x in data) + ");")
附加提速点:PRAGMA 设置与 WAL 模式
事务提速不止靠“包一起”,还要减少日志和锁竞争:
- 开启 WAL 模式:
conn.execute("PRAGMA journal_mode = WAL"),允许多读一写并发,且日志写入更轻量 - 临时关闭同步:
conn.execute("PRAGMA synchronous = OFF")(仅开发/导入场景用,断电可能丢最近几条) - 增大缓存页:
conn.execute("PRAGMA cache_size = 10000"),减少磁盘换页 - 这些 PRAGMA 必须在
BEGIN之前设置,否则无效
完整轻量模板:
conn = sqlite3.connect("fast.db")
conn.execute("PRAGMA journal_mode = WAL")
conn.execute("PRAGMA synchronous = NORMAL") # 平衡安全与速度
conn.execute("BEGIN")
for i in range(0, len(data_list), 500):
batch = data_list[i:i+500]
conn.executemany("INSERT INTO t (a,b) VALUES (?,?)", batch)
conn.commit()
事务边界、批大小、PRAGMA 配置三者必须协同;单独调大某一项,其他没跟上,性能提升会迅速触顶。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










