bulk_insert_mappings()适用于已有字典列表且无需触发orm事件的场景,它跳过对象实例化、直接生成批量sql,性能远超add_all()和循环add(),但需手动补全default字段并控制单次提交量(建议≤5000条)。

直接用 bulk_insert_mappings() 或 to_sql(),别用 add() 循环插入——后者在万级数据下会慢 10 倍以上。
什么时候该用 bulk_insert_mappings() 而不是 add_all()
当你已有字典列表(比如从 JSON、API 或 Pandas to_dict('records') 得来),且不需要触发 ORM 事件(如 @validates、before_insert)时,bulk_insert_mappings() 是最优选。
-
add_all([User(**d) for d in data])仍要实例化每个对象,走完整 ORM 生命周期,内存和 CPU 开销大 -
bulk_insert_mappings(User, data)跳过对象构造,直接拼 SQL,速度接近原生executemany() - 不支持
default/server_default字段的自动填充,需提前补全字典中的键(比如'created_at': datetime.now()) - 批量提交前务必控制数量:单次传入超过 5000 条可能触发 PostgreSQL 的参数绑定限制或 MySQL 的
max_allowed_packet
pd.DataFrame.to_sql() 的隐藏陷阱与调优点
用 Pandas 写库最省事,但默认行为在生产环境容易翻车。
-
if_exists='append'是安全起点,但默认index=False必须显式写上,否则会多写一列index字段 - MySQL 下默认使用
INSERT INTO ... VALUES单语句,每行一条——换成method='multi'可合并为一条多值 INSERT,提速 3–5 倍 - PostgreSQL 用户应优先考虑
method=lambda _, df: pg_copy_from(df)配合copy_from(),比to_sql()快一个数量级 - 字段名含大小写或特殊字符时,
to_sql()可能报ProgrammingError: (psycopg2.errors.UndefinedColumn),加schema参数或统一小写列名可规避
绕过 ORM 直接执行 COPY(PostgreSQL)或 LOAD DATA(MySQL)
这是真正意义上的“高效”——适用于初始化、ETL、日志归档等无业务逻辑的纯写入场景。
- PostgreSQL:
engine.raw_connection()+copy_from(StringIO, table_name),要求数据是制表符分隔、无 header 的字符串流 - MySQL:
LOAD DATA LOCAL INFILE需服务端开启local_infile=1,且 Python 客户端要传connect_args={'local_infile': True} - 两者都不走 SQLAlchemy 连接池,需手动管理连接生命周期;失败时不会自动 rollback,错误定位也更原始(比如 CSV 格式错直接报
psycopg2.errors.InvalidTextRepresentation) - 无法利用模型定义的类型转换(如
JSON字段会当字符串写入),必须预处理成目标格式
真正卡住性能的往往不是语法,而是事务粒度和索引。批量写入前禁用非必要索引,写完再重建;每 500–1000 条 commit 一次,避免长事务锁表或 WAL 日志暴涨——这些细节比选哪个函数更重要。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











