async def create_category(db: Session, task_id, category_list, create_time):
db_categorys = [models.TaskDataSetCategory(
task_id=task_id,
category_id=index + 1,
name=tag,
supercategory='',
create_time=create_time,
update_time=create_time
) for index, tag in enumerate(category_list)]
await db.run_sync(lambda session: session.bulk_save_objects(db_categorys))
最后一句
核心机制解析
-
db.run_sync()
方法:-
这是 SQLAlchemy 异步 API(
AsyncSession
)的关键桥接方法 -
作用:在异步环境中执行同步风格的 SQLAlchemy 操作
-
原理:将同步代码转移到专门的事件循环执行器中运行,避免阻塞主线程
-
-
lambda 函数:
lambda session: session.bulk_save_objects(db_categorys)
-
接收同步风格的
Session
对象作为参数 -
调用同步的
bulk_save_objects()
方法批量保存对象
-
-
bulk_save_objects()
方法:-
高效保存对象列表(比逐个
add()
性能更高) -
特点:
-
不触发 ORM 事件(如
before_insert
) -
不自动获取生成的主键值
-
适合批量初始化数据场景
-
-
执行流程分解
-
当前线程(异步上下文)暂停执行
-
SQLAlchemy 将 lambda 函数交给后台同步执行器
-
同步执行器:
-
获取传统同步 Session
-
执行批量插入操作
-
生成如下等效 SQL:
INSERT INTO task_data_set_category (task_id, category_id, name, supercategory, create_time, update_time) VALUES (?,?,?,?,?,?), (?,?,?,?,?,?), ...;
-
-
操作完成后返回异步上下文继续执行
性能优化说明
方法 | 耗时示例 (1000条) | 特点 |
---|---|---|
逐个 session.add() |
~500ms | 触发ORM事件,有完整生命周期 |
bulk_save_objects |
~50ms | 无事件触发,纯SQL批量插入 |
注意事项
-
主键获取:
-
批量保存后
db_categorys
中的对象不会自动获得主键值 -
如需主键需要额外查询或配置
return_defaults=True
-
-
关联对象:
-
不会自动处理关系对象的保存
-
需要预先确保所有外键关系有效
-
-
异步上下文:
-
必须在
async with AsyncSession() as db:
块内使用 -
禁止在普通同步函数中直接调用
-