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

为何未用joinedload仍可访问关联对象?额外查询何时触发?

问题描述

以下是一段SQLAlchemy代码:

class Items(Base):
    tag_id = Column(Integer, ForeignKey(Tag.id, ondelete='CASCADE'), index=True)
    ...
    tag = relationship('Tag', back_populates='items')

query = Select(Items)
cursor = await db_session.execute(query)
items = cursor.scalars().all()
print(items[0].tag.id)  # 123

上述代码中未使用joinedload却能正常访问Items关联的Tag对象id属性,请问这一现象的原因是什么?针对关联表的额外查询会在何时执行?


解答

1. 无需joinedload即可访问tag.id的原因

因为Items类中已经定义了tag_id这个外键字段,执行Select(Items)查询时,该字段的值已经被加载到Items实例里。SQLAlchemy有个优化逻辑:当访问关联对象tag的主键id时,会直接复用当前Items实例已有的tag_id值,完全不需要去查询Tag表。

简单来说,这里的tag.id本质上就是items[0].tag_id的映射,SQLAlchemy帮你省略了重复查询的步骤。

2. 关联表额外查询的触发时机

只有当你访问Tag对象的非主键属性时,才会触发额外的SELECT查询。比如执行print(items[0].tag.name)时,SQLAlchemy发现Tag对象的name属性未被加载,就会自动执行一条针对Tag表的查询(SELECT * FROM tag WHERE id = ?),获取完整的Tag记录。

这是SQLAlchemy默认的**延迟加载(lazy loading)**行为,默认情况下relationship的lazy参数为select,只会在首次访问关联对象的非主键属性时触发查询。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:12:34