回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<p>我有一些数据库结构;因为大部分与我们无关,所以我只描述一些相关的部分。以lake Item对象为例:</p>
<pre>items_table = Table("invtypes", gdata_meta,
Column("typeID", Integer, primary_key = True),
Column("typeName", String, index=True),
Column("marketGroupID", Integer, ForeignKey("invmarketgroups.marketGroupID")),
Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True))
mapper(Item, items_table,
properties = {"group" : relation(Group, backref = "items"),
"_Item__attributes" : relation(Attribute, collection_class = attribute_mapped_collection('name')),
"effects" : relation(Effect, collection_class = attribute_mapped_collection('name')),
"metaGroup" : relation(MetaType,
primaryjoin = metatypes_table.c.typeID == items_table.c.typeID,
uselist = False),
"ID" : synonym("typeID"),
"name" : synonym("typeName")})</pre>
<p>我想在sqlalchemy/database层实现一些性能改进,并有一些想法:
1) 两次请求同一物品:</p>
^{pr2}$
<p>每个请求生成并发出SQL查询。为了避免这种情况,我对一个item对象使用了两个自定义映射:</p>
<pre>itemMapId = {}
itemMapName = {}
@cachedQuery(1, "lookfor")
def getItem(lookfor, eager=None):
if isinstance(lookfor, (int, float)):
id = int(lookfor)
if eager is None and id in itemMapId:
item = itemMapId[id]
else:
item = session.query(Item).options(*processEager(eager)).get(id)
itemMapId[item.ID] = item
itemMapName[item.name] = item
elif isinstance(lookfor, basestring):
if eager is None and lookfor in itemMapName:
item = itemMapName[lookfor]
else:
# Items have unique names, so we can fetch just first result w/o ensuring its uniqueness
item = session.query(Item).options(*processEager(eager)).filter(Item.name == lookfor).first()
itemMapId[item.ID] = item
itemMapName[item.name] = item
return item</pre>
<p>我相信sqlalchemy也做类似的对象跟踪,至少通过主键(项目编号). 若确实如此,我可以擦除这两个映射(尽管擦除名称映射将需要对使用这些查询的应用程序进行小的修改),以避免重复功能和使用常用方法。实际的问题是:如果sqlalchemy中有这样的功能,如何访问它?在</p>
<p>2)快速加载关系通常有助于将大量请求保存到数据库。例如,我肯定需要以下一组item=item()属性:</p>
<pre>item.group (Group object, according to groupID of our item)
item.group.items (fetch all items from items list of our group)
item.group.items.metaGroup (metaGroup object/relation for every item in the list)</pre>
<p>如果我有一些条目ID,但是还没有加载条目,我可以从数据库中请求它,急切地加载我需要的一切:sqlalchemy将在单个查询中联接group、它的条目和相应的元组。如果我使用默认的延迟加载访问它们,sqlalchemy将需要发出1个查询来获取item+1以获取列表中所有项的group+1*#items+1*#items以获取每个项的元组,这是浪费。在</p>
<p>2.1)但是如果我已经获取了Item对象,并且我想要加载的一些属性已经加载了呢?据我所知,当我从数据库中重新获取某个对象时,它已经加载的关系不会被卸载,对吗?在</p>
<p>2.2)如果我已经获取了Item对象,并且想访问它的组,我可以使用项目组ID,应用我需要的任何急切的陈述(“项目”和“项目.元组"). 它应该正确地加载组和它所请求的关系,而不需要接触项目内容。sqlalchemy会正确地将这个获取的组映射到项目组,这样当我访问项目组它不会从底层数据库中获取任何内容?在</p>
<p>2.3)如果我从数据库中提取了以下内容:原始项,项目组还有一部分item.group.items项列出其中一些可能已经加载了元组,完成数据结构的最佳策略与上面的eager list相同:使用(“items”重新获取组项目.元组“)紧急加载,或者分别检查项目列表中的每个项目,如果项目或其元组未加载-加载它们?这似乎取决于具体情况,因为如果所有的东西都在一段时间前就已经加载了,那么发出如此繁重的查询是毫无意义的。sqlalchemy是否提供了一种跟踪某个对象关系是否已加载的方法,并且能够深入查看一个级别吗?在</p>
<p>作为2.3的一个例子-我可以获取ID为83的组,急切地获取“items”和项目.元组". 有没有办法从一个条目(groupID为83)中确定它是否有“group”组.项“和”group.items.metaGroup组“是否加载,使用sqlalchemy工具(在本例中,应该加载所有工具)?在</p>