You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Sqlalchemy ORM执行单查询更新及效率对比

问题1:第一种常规写法是否产生两次数据库请求?

是的,该写法会产生两次数据库往返:

  • 第一次是执行session.query(Dummy).filter(Dummy.id == 1).first()时发送的SELECT查询,用于获取目标ORM实例
  • 第二次是执行session.commit()时发送的UPDATE语句,提交属性变更

如果在修改属性和commit之间执行过session.flush(),UPDATE会提前到flush阶段发送,本质还是两次请求。

问题2:第二种update写法是否效率更高?

是的,第二种写法效率明显更高。
该写法会直接生成对应的UPDATE语句发送到数据库,全程只需要1次数据库往返,没有前置的SELECT查询,单条更新的性能就有优势,如果是批量更新场景,性能差距会非常大。
但要注意两个默认限制:

  • 该操作属于bulk级操作,不会触发ORM实例级的before_update、after_update等监听器,也不会自动处理实例的关联关系同步
  • 如果当前session中已经缓存了id=1的Dummy实例,该操作不会自动更新缓存中的实例属性,后续再从session中读取该实例会拿到旧值,需要手动调用session.expire(dummy_instance)或者session.refresh(dummy_instance)刷新缓存。

问题3:需要触发ORM监听器的场景如何处理?

分两种场景选择方案:

单条/小批量更新场景

如果更新量级很小,直接使用第一种常规写法即可,两次请求的开销可以忽略,能天然兼容所有ORM监听器逻辑。如果需要避免并发更新冲突,可以在查询时加行锁:

dummy = session.query(Dummy).filter(Dummy.id == 1).with_for_update().first()
dummy.name = "dumb-dumb"
session.commit()

大量数据更新场景

如果需要兼顾更新性能和监听器逻辑,可以选择以下两种方案:

  1. 改用会话级/语句级事件监听:不使用实例级的update监听器,改为监听before_execute或after_execute事件,匹配对应的UPDATE语句后执行自定义逻辑,该类监听器对bulk update、Core update语句都生效,不需要加载ORM实例,也不会产生额外查询。
  2. 若必须使用实例级监听器,可以先批量查询出所有需要更新的实例(1次SELECT),遍历修改属性后统一commit(批量UPDATE会优化为更少的请求),相比单条两次请求的写法,性能也会有明显提升。

内容的提问来源于stack exchange,提问作者Walrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 00:39:03