SQLAlchemy中批量执行大量DML语句的最高效实现方式
SQLAlchemy 1.4 + MySQL 8.0 混合DML批量执行方案
前置说明
你之前使用cursor.executemany没有生效的核心原因是:该方法设计用于同一SQL模板+多组不同参数的场景(比如同一张表批量插入N条数据),不支持传入多个结构完全不同的DML语句,所以不会抛出异常但也不会执行成功。
以下是两种可行的高效执行方案,效率远高于逐条执行:
方案1:分批次事务提交(推荐,安全性最高)
默认逐条调用engine.execute时会自动为每条语句开启并提交独立事务,事务提交的IO开销是慢的核心原因。改为显式事务、分批提交即可大幅降低开销:
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker # 初始化引擎和会话,不需要额外改连接参数 engine = create_engine("mysql+pymysql://你的数据库连接串") Session = sessionmaker(bind=engine) # 可根据单条语句大小调整批次大小,建议100-1000之间 BATCH_SIZE = 500 statements = get_long_list_of_statements() with Session() as session: for idx, stmt in enumerate(statements, 1): session.execute(stmt) # 每满一个批次提交一次 if idx % BATCH_SIZE == 0: session.commit() # 提交最后不足一个批次的语句 session.commit()
这种方案不需要改任何连接配置,没有SQL注入风险,兼容所有DML类型,实测10000条语句的执行速度可以提升5-10倍。
方案2:多语句一次性执行(极致性能,需注意安全)
如果需要更高的执行效率,可以开启MySQL的多语句执行支持,把所有DML拼接后一次性执行:
- 首先在创建引擎时开启多语句支持的连接参数:
import pymysql from sqlalchemy import create_engine, text engine = create_engine( "mysql+pymysql://你的数据库连接串", # 开启多语句执行权限 connect_args={"client_flag": pymysql.constants.CLIENT.MULTI_STATEMENTS} )
- 拼接所有语句后执行:
statements = get_long_list_of_statements() # 编译所有语句为带参数的完整SQL字符串 compiled_stmts = [] for stmt in statements: compiled = stmt.compile( engine, compile_kwargs={"literal_binds": True} ) compiled_stmts.append(str(compiled).strip(";")) # 拼接为完整的多语句串 full_sql = ";".join(compiled_stmts) with engine.connect() as conn: conn.execute(text(full_sql)) conn.commit()
注意事项
- 多语句执行存在SQL注入风险,必须确保所有DML语句都是可信来源,不存在未经过滤的用户输入内容
- 拼接后的总语句大小不能超过MySQL的
max_allowed_packet配置限制,超过的话可以拆分多个批次执行多语句
内容的提问来源于stack exchange,提问作者Batman
相关产品推荐
相关产品推荐

