0

我一直在使用 Google App Engine,但我的一些数据查询遇到了一些性能缓慢的问题。我读过设计 App Engine 数据存储区与使用 SQL 数据库的思维方式不同,我不确定我这样做是不是最好的方式。我有两个问题要尝试走上正轨:

具体来说:

我有一个Foo类型和一个UserFoo类型。每个UserFoo都是对应的“实例”,Foo并保存特定于该实例的数据。我的Foo类型有一个fooCode属性,它是一个唯一标识符,我使用它们的UserFoo属性来映射它们。然后我使用如下代码对每个 Foo 进行操作:FoofooCode

foos = Foo.all().filter('bar =', bar)
for foo in foos:
    userFoo = UserFoo.all().filter('userKey =', user).filter('fooCode =', foo.fooCode)

注意:我使用fooCode的是引用键,以便我们可以轻松地删除和重新添加新Foo的 s,而不必重新映射所有相应UserFoo的 s。

一般来说:

设计 GAE 数据存储表的典型方法和使用它们的最佳实践是什么?

4

3 回答 3

1

一般来说:

  • 尽可能地去规范化。

  • 尽可能通过其密钥引用实体;这是从数据存储中获取数据的最快方法。

具体来说,如果您使用 ReferenceProperty 而不是进入过滤器的代码来建立关系,那么您的性能可能会显着提高。我猜想查询 UserFoo 的 Foo 比删除和重新映射 Foo 更频繁,是吗?在这种情况下,务实和明智的做法是使用引用属性。

此外,如果 Foo-UserFoo 关系可以非规范化为单个实体,则您完全不需要整个系列的查询。

于 2010-08-03T20:01:27.820 回答
1

这是获取反模式的阶梯。解决方案是ReferenceProperty 预取

问题是您决定不使用 ReferenceProperty。我建议你重新考虑这个选择。

注意:我在引用键上使用 fooCode,以便我们可以轻松删除和重新添加新的 Foo,而不必重新映射所有相应的 UserFoo。

请记住,实体键只是其路径的编码表示:实体及其任何祖先的种类和名称或 ID。如果您删除然后重新创建了一个Foo,则只有在为其赋予不同的名称或 ID 时,它才会具有不同的键。如果您有某种方法可以使旧实体和新实体相同fooCode,则可以轻松地将fooCode用作键名,这将允许删除然后重新添加Foo以保留其原始键。

于 2010-08-03T20:05:13.207 回答
1

我建议进行以下更改:

  1. 在 UserFoo 中使用 ReferenceProperty 来引用其 Foo,或在适当的情况下使其成为子实体。我不明白您关于重新映射现有实体的评论 - 这绝不是必要的。
  2. 将 'bar' 属性的副本添加到每个 UserFoo
  3. 对 UserFoo.all().filter('bar =', bar).order('userKey') 执行单个查询。结果将按栏过滤并按用户分组,并且只需要一个查询,而不是每个用户一个查询。
  4. 通过在查询上调用 .fetch() 来一次获取结果,而不是遍历它们。这效率更高。
  5. 如果需要,使用ReferenceProperty 预取来检索每个 UserFoo 的 Foo 对象。
于 2010-08-04T12:14:41.633 回答