就我而言,对底层数据库的查询非常昂贵,所以我们尽可能地尝试保存数据库请求。
这是我将用于示例的简化数据库:
items_table = Table("invtypes", gdata_meta,
Column("typeID", Integer, primary_key = True),
Column("typeName", String, index=True),
Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True))
mapper(Item, items_table,
properties = {"group" : relation(Group, backref = "items"),
"ID" : synonym("typeID"),
"name" : synonym("typeName")})
groups_table = Table("invgroups", dbmetadata,
Column("groupID", Integer, primary_key = True),
Column("groupName", String))
mapper(Group, groups_table,
properties = {"ID" : synonym("groupID"),
"name" : synonym("groupName")})
然后我们获取一些Item对象和其中一个组:
engine = create_engine("sqlite:///<path-to-db>", echo=True)
Session = sessionmaker(bind=engine)
session = Session()
itm = session.query(Item).get(11184) #1
grp = session.query(Group).get(831) #2
在这种特殊情况下,itm.groupID = 831,因此itm的组已经加载到内存中。但是:
>>>attributes.instance_state(itm).unloaded
set(['group', 'name', 'ID'])
SQLAlchemy表示卸载'itm'的'group'属性/关系。但是,在这种情况下,访问它时,不会向底层数据库发出任何查询,因为它已经在标记为#2的行中加载。第一次访问后,它不再标记为已卸载。
现在让我们完成上面的例子并进行一般性的讨论。访问Item对象的group属性时,可以在某处(即已在当前会话中映射)引用具有请求ID的组,或者仅存在于基础数据库中。
我目前的目标是找到一种方法可靠地确定具有给定ID及其'group'属性/关系的Item是否已经加载到内存中或执行itm加载,然后itm.group acccess,以及SQLAlchemy是否无法提取某些内容它的对象映射,即将向底层数据库发出查询 - 拦截它并发出另一个数据库请求。这应该保证它最多只需要一个数据库请求(必要时需要加载)以加载我需要的所有内容,或者如果所有内容都已加载则为零请求。
正如我在上面的一段中所描述的,attributes.instance_state()。unloaded不是一种可靠的方法。它不会检测从未访问过的属性/关系的实际加载状态。
我打算用它来优化涉及预先加载的查询(即,在所有请求的对象都已加载的情况下,这种情况经常在我的情况下发生,并且当这些查询不同时,查询缓存不起作用)他们)。