execute_values()比executemany()快得多,因其将多行拼为单条VALUES语法(如INSERT...VALUES (1,2),(3,4)),一次网络往返完成;而executemany()默认逐行执行,I/O与解析开销大,实测快5–10倍。

为什么 execute_values() 比 executemany() 快得多
因为 execute_values() 把多行数据拼成一条 PostgreSQL 的 VALUES 批量语法(如 INSERT INTO t (a,b) VALUES (1,2), (3,4), (5,6)),一次网络往返就发完;而 executemany() 默认对每条记录生成独立 INSERT 语句,或退化为多次 prepare + execute,I/O 和解析开销翻倍。实测 10 万行插入,前者通常快 5–10 倍,且更省连接资源。
注意:它不是 Psycopg2 原生方法,而是 psycopg2.extras 提供的扩展函数,需显式导入。
怎么调用 execute_values() 才不报错
常见报错如 AttributeError: module 'psycopg2.extras' has no attribute 'execute_values',说明版本太低——必须用 Psycopg2 ≥ 2.8。旧版用户请先升级:pip install --upgrade psycopg2-binary。
调用时关键点:
立即学习“Python免费学习笔记(深入)”;
-
execute_values()第一个参数是cursor,不是connection - 第二参数是数据列表,每个元素必须是
tuple或dict(后者需配page_size和列名) - 第三参数
sql是带占位符的模板字符串,**必须用%s,不能用{}或:name** - 若字段含 JSON、数组等特殊类型,确保数据库列类型匹配,否则会触发
ProgrammingError
示例:
from psycopg2.extras import execute_values
# ...
execute_values(
cur,
"INSERT INTO users (id, name, email) VALUES %s",
[(1, 'Alice', 'a@b.com'), (2, 'Bob', 'b@c.com')],
page_size=1000
)
page_size 设多大才合理
page_size 控制每批发送多少行,默认 100。设太大(如 10000)可能触发 PostgreSQL 的 max_stack_depth 或内存溢出;设太小(如 10)又失去批量意义。实际建议按以下条件选:
- 单行平均字节数
- 含大字段(
TEXT,JSONB)→ 降到 100–500 - 高并发写入场景 → 保守取 100,避免长事务阻塞其他操作
- 不确定时,先用 500 测速,再微调
它不影响正确性,只影响性能和稳定性。超过 page_size 的数据会被自动分片,无需手动切分。
遇到 UnicodeEncodeError 或 NULL 字段怎么处理
典型错误:UnicodeEncodeError: 'utf-8' codec can't encode character '\ud83d'...,多因 Python 字符串含 surrogate pair(如某些 emoji),而老版本 PostgreSQL 客户端编码未正确识别。解决方式:
- 连接时强制指定编码:
conn = psycopg2.connect(..., options='-c client_encoding=UTF8') - 或升级到 Psycopg2 ≥ 2.9.3,已修复 surrogate 处理逻辑
- NULL 值直接传
None,execute_values()原生支持,无需预处理 - 但注意:如果表定义某列为
NOT NULL却传了None,会抛IntegrityError,这不是函数问题,是数据校验失败
别试图用 str(x) if x is not None else 'NULL' 手动转——这会让 NULL 变成字符串 'NULL',写入后变成文本而非 SQL NULL。
真正难调的其实是字段类型隐式转换:比如 Python float('inf') 插入 NUMERIC 列会失败,而 execute_values() 不做中间校验,错误直到执行才暴露。这类问题得靠上游数据清洗,或者加一层 try/except 包裹并记录坏行索引。


















