2010-05-12 56 views
2

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() 

当我喜欢编码以下,这是可怕的慢(几乎3S)与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 

如何优化此代码?请考虑应为每个部队/单位组计算更多属性,我不想将这些集体属性保存到每个实体。 :)

回答

2

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

将实体放置在实体组中是通过在创建实体组时将其实体设置为来实现的。一旦完成,你可以获得属于某个部队的所有单位,只有一个ancestor query

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

+0

小心不要创建太大的实体组。同一实体组中的所有内容都必须位于同一台服务器上,Google会对可同时进行多少次更新提出一些限制。请参阅本页顶部的说明http://code.google.com/appengine/articles/sharding_counters.html – user27478 2010-05-13 17:23:18

+0

绝对正确,@gerdemb。 – 2010-05-13 17:58:15

2

存储在App Engine上很便宜,CPU和请求时间也少了很多。关于数据存储的主要内容是您应该优化的读取,而不是写入 - 最终您的数据读取将比您写入数据的次数多得多。

如果你认为你可能永远需要知道Force的总hp,你应该把它保存在一个名为total_hp场,并用新的值更新每次更新/添加/删除其UnitGroup S和Unit时间秒。您也应该在交易中这样做,这意味着他们需要位于同一个实体组中。

相关问题