- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一些数据库结构;由于大部分内容与我们无关,我将仅描述一些相关部分。让我们以湖 Item 对象为例:
items_table = Table("invtypes", gdata_meta,
Column("typeID", Integer, primary_key = True),
列("typename",字符串,索引=真),
列(“marketGroupID”,整数,外键(“invmarketgroups.marketGroupID”)),
列(“groupID”,整数,外键(“invgroups.groupID”),索引=真))
映射器(项目,项目表,
属性= {“组”:关系(组,backref =“项目”),
“_Item__attributes”:relation(Attribute, collection_class = attribute_mapped_collection('name')),
“效果”:关系(效果,collection_class = attribute_mapped_collection('name')),
“元组”:关系(元类型,
primaryjoin = metatypes_table.c.typeID == items_table.c.typeID,
使用列表 = 假),
“ID”:同义词(“typeID”),
“名称”:同义词("typename")})
我想在 sqlalchemy/database 层实现一些性能改进,并且有几个想法:
1) 两次请求相同的项目:
item = session.query(Item).get(11184)
item = None(对 item 的引用丢失,对象被垃圾回收)
item = session.query(Item).get(11184)
每个请求都会生成并发出 SQL 查询。为了避免它,我为一个项目对象使用了 2 个自定义映射:
itemMapId = {}
itemMapName = {}
@cachedQuery(1, "查找")
def getItem(寻找,渴望=无):
if isinstance(lookfor, (int, float)):
id = int(查找)
如果eager 是None 并且itemMapId 中的id:
item = itemMapId[id]
别的:
item = session.query(Item).options(*processEager(eager)).get(id)
itemMapId[item.ID] = item
itemMapName[item.name] = item
elif isinstance(lookfor, basestring):
如果eager 是None 并在itemMapName 中查找:
item = itemMapName[查找]
别的:
# 项目有唯一的名字,所以我们可以只获取第一个结果而不确保它的唯一性
item = session.query(Item).options(*processEager(eager)).filter(Item.name == lookfor).first()
itemMapId[item.ID] = item
itemMapName[item.name] = item
归还元素
我相信 sqlalchemy 至少通过主键 (item.ID) 进行类似的对象跟踪。如果是这样,我可以删除两个映射(尽管删除名称映射需要对使用这些查询的应用程序进行细微修改),以免重复功能并使用常用方法。实际问题是:如果 sqlalchemy 中有这样的功能,如何访问它?
2)急切加载关系通常有助于节省对数据库的大量请求。说,我肯定需要以下一组 item=Item() 属性:
item.group (Group 对象,根据我们 item 的 groupID)
item.group.items(从我们组的项目列表中获取所有项目)
item.group.items.metaGroup(列表中每个项目的元组对象/关系)
如果我有一些项目 ID 并且还没有加载项目,我可以从数据库中请求它,急切地加载我需要的一切:sqlalchemy 将在单个查询中加入组、它的项目和相应的元组。如果我使用默认的延迟加载访问它们,sqlalchemy 将需要发出 1 个查询来获取项目 + 1 以获取组 + 1*#items 列表中的所有项目 + 1*#items 以获取每个项目的元组,这是浪费。
2.1) 但是如果我已经获取了 Item 对象,并且我想要加载的一些属性已经加载了怎么办?据我了解,当我从数据库中重新获取某个对象时 - 它已经加载的关系不会被卸载,我对吗?
2.2) 如果我获取了 Item 对象,并想访问它的组,我可以使用 item.groupID 来获取组,应用我需要的任何急切语句(“items”和“items.metaGroup”)。它应该正确加载组及其请求的关系,而无需接触项目内容。 sqlalchemy 会将此获取的组正确映射到 item.group,以便当我访问 item.group 时它不会从底层数据库中获取任何内容吗?
2.3)如果我从数据库中提取了以下内容:原始项目、item.group 和 item.group.items 列表中的部分项目,其中一些可能加载了 metaGroup,那么完成数据结构的最佳策略是什么?与上面的急切列表相同:使用(“items”,“items.metaGroup”)急切加载重新获取组,或单独检查项目列表中的每个项目,如果项目或其元组未加载 - 加载它们?这似乎取决于情况,因为如果一切都已经在一段时间前加载了 - 发出如此繁重的查询是没有意义的。 sqlalchemy 是否提供了一种方法来跟踪是否加载了某个对象关系,并且能够查看更深的层次而不仅仅是一个级别?
作为 2.3 的说明 - 我可以获取 ID 为 83 的组,急切地获取“items”和“items.metaGroup”。有没有一种方法可以使用 sqlalchemy 工具(在这种情况下所有的其中应该加载)?
最佳答案
要强制加载惰性属性,只需访问它们。这是最简单的方法,它适用于关系,但对于 Column
效率不高。 s(对于同一个表中的每一列,您将获得单独的 SQL 查询)。您可以从 sqlalchemy.orm.attributes.instance_state(obj).unloaded
获取所有未加载属性(关系和列)的列表。 .
您在示例中不使用延迟列,但为了完整起见,我将在此处对其进行描述。处理延迟列的典型场景如下:
deferred()
装饰选定的列.使用 group
将它们组合成一组或几组deferred()
的参数. undefer()
和 undefer_group()
需要时查询中的选项。 column_property(Column(…), group=…)
推迟加载它们。 ,但是
defer()
选项不会影响它们(它仅适用于
Column
s,不适用于列属性,至少在 0.6.7 中)。
session.refresh(obj, attribute_names=…)
Nathan Villaescusa 建议的可能是最好的解决方案。我看到的唯一缺点是它首先使属性过期,因此您必须确保在以
attribute_names
传递的方式中没有加载的属性。参数(例如,使用与
state.unloaded
的交集)。
weak_identity_map=False
更改此设置),因此一旦您的代码中没有对它的引用,该对象就会从缓存中删除。 SQLAlchemy 不会对
query.get(pk)
执行 SQL 请求当对象已经在 session 中时。但这适用于
get()
仅方法,所以
query.filter_by(id=pk).first()
将使用加载的数据在 session 中执行 SQL 请求和刷新对象。
item.group
使用
query.get()
加载方法,因此如果对象已经在 session 中,则不会导致 SQL 请求。
state.unloaded
检查相关对象的关系是否已加载。因此递归到任何深度。但是当关系尚未加载时,您无法知道相关对象及其关系是否已经加载:即使关系尚未加载,相关对象 [s] 也可能已经在 session 中(想象一下您请求第一项,加载其组,然后请求具有相同组的其他项目)。对于您的特定示例,我认为只需检查
state.unloaded
就没有问题递归地。
关于python - 完成对象及其关系并避免在 sqlalchemy 中进行不必要的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5795492/
jQuery attributeContainsPrefix [name^="value"] 对比 attributeStartsWith [name|="value"] 实际区别是什么? 最佳答案
在1.1部分在RFC 6749中,有四种角色:资源拥有者、资源服务器、客户端和授权服务器。 如果客户端和资源所有者是同一实体,OAuth 是否变得多余或不必要? 例如,我有一个封闭的 API 和一个面
我有一段代码,其中有一个带有保护子句的 raise 语句: def validate_index index # Change to SizeError raise ArgumentError
我看到了这篇文章( JPA Entity Lifecycle Events vs database trigger ),但它并没有像我在这里那样明确地询问: 当我插入 PK 值为 (null) 的行时
所以,我有一段代码看起来像 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ // Do something }
我是一名优秀的程序员,十分优秀!