应用引擎的反向引用太慢了。我怎样才能让它更快?

时间:2010-05-12 09:09:23

标签: google-app-engine google-cloud-datastore

Google应用引擎具有名为后向引用的智能功能,我通常会在需要使用传统SQL计算列的地方进行迭代。

想象一下需要累积特定力量的总hp。

class Force(db.Model):
  hp = db.IntegerProperty()
class UnitGroup(db.Model):
  force = db.ReferenceProperty(reference_class=Force,collection_name="groups")
  hp = db.IntegerProperty()
class Unit(db.Model):
  group = db.ReferenceProperty(reference_class=UnitGroup,collection_name="units")
  hp = db.IntegerProperty()

当我编写如下代码时,它的速度非常慢(差不多3秒),其中20个力量单组 - 单个单位。 (我想反向引用强制重载子实体。我是对的吗?)

def get_hp(self):
    hp = 0
    for group in self.groups:
        group_hp = 0
        for unit in group.units:
            group_hp += unit.hp
        hp += group_hp
    return hp

如何优化此代码?请考虑应为每个force / unit-groups计算更多属性,并且我不想将这些集合属性保存到每个实体。 :)

2 个答案:

答案 0 :(得分:2)

Force,UnitGroup和Unit似乎很适合Entity Group。每个Unit属于一个且只有一个UnitGroup并且每个UnitGroup属于一个且只有一个Force,这是真的吗?如果是这样,那么您可以将这些实体存储为实体组,并使用祖先查询来减少数据存储查询的数量。

将实体放入实体组是通过在创建实体时设置其属性来完成的。完成后,您可以使用单个ancestor query获取属于某个部队的所有单位。

话虽如此,正确的做法是在将实体写入数据库时​​计算值,而不是在读取它们时。这个和其他地方一遍又一遍地注意到这个简单的事实,它是从AppEngine应用程序中获得良好性能的最佳方式。它可能看起来像预先做了很多工作,对于那些拥有传统SQL数据库背景的人来说,这是非常反直觉的,但这是你想要做的,简单明了。

答案 1 :(得分:2)

App Engine上的存储成本很低,而CPU和请求时间则较少。关于数据存储区,你应该记住的主要事情是你应该优化读取而不是写入 - 你最终会比编写数据更频繁地读取数据。

如果您认为自己可能需要知道Force的总hp,则应将其存储在名为total_hp的字段中,并每次使用新值更新您更新/添加/删除其UnitGroupUnit。您也应该在事务中执行此操作,这意味着它们需要位于同一个实体组中。