【问题标题】:appengine: cached reference property?appengine:缓存的引用属性?
【发布时间】:2010-11-13 12:43:10
【问题描述】:

如何在 Google App Engine 中缓存引用属性?

例如,假设我有以下模型:

class Many(db.Model):
    few = db.ReferenceProperty(Few) 

class Few(db.Model):
    year = db.IntegerProperty()

然后我创建了许多Many,它们只指向一个Few

one_few = Few.get_or_insert(year=2009)
Many.get_or_insert(few=one_few)
Many.get_or_insert(few=one_few)
Many.get_or_insert(few=one_few)
Many.get_or_insert(few=one_few)
Many.get_or_insert(few=one_few)
Many.get_or_insert(few=one_few)

现在,如果我想遍历所有 Many,读取它们的 few 值,我会这样做:

for many in Many.all().fetch(1000):
  print "%s" % many.few.year

问题是:

  • 每次访问many.few 都会触发数据库查找吗?
  • 如果是,是否可以缓存某处,因为每次只需一次查找就足以带来相同的实体?

正如一条评论中所述:我知道 memcache,但是当我通过引用调用另一个实体时,我不确定如何“注入”它。

在任何情况下,memcache 都不会有用,因为我需要在执行中进行缓存,而不是在它们之间。使用 memcache 无助于优化此调用。

【问题讨论】:

    标签: python database performance google-app-engine google-cloud-datastore


    【解决方案1】:

    第一次取消引用任何引用属性时,会提取实体 - 即使您之前提取了与不同引用属性关联的同一实体。这涉及到数据存储获取操作,它不像查询那样昂贵,但如果可以的话,仍然值得避免。

    有一个很好的模块可以无缝缓存可用的实体here。它在数据存储的较低级别工作,并将缓存所有数据存储获取,而不仅仅是取消引用 ReferenceProperties。

    如果您想一次解析一堆引用属性,还有另一种方法:您可以在一次往返中检索所有键并获取实体,如下所示:

    keys = [MyModel.ref.get_value_for_datastore(x) for x in referers]
    referees = db.get(keys)
    

    最后,我编写了一个库,该库对 db 模块进行猴子补丁,以根据每个请求在本地缓存实体(不涉及内存缓存)。它可用,here。不过有一个警告:它有单元测试,但没有被广泛使用,所以它可能会被破坏。

    【讨论】:

    • 我知道第一次调用model1.reference时,它会加载引用,然后再加载。我的问题是当我调用 model2.reference 时 - 如果两个引用都指向同一个实体,App Engine 会在再次访问数据存储之前捕获并停止吗?
    • 我检查了模块,似乎它完成了 memcache 部分。但是 memcache 对暴露的情况没有用:(。无论如何感谢您的参考,它将很有用。
    • 不,App Engine 将进行第二次往返。缓存库会将其转换为 memcache 往返,这是一种改进 - 但它当然也可以使用增强功能在每个请求的基础上进行本地缓存。我已经写了这样一个库 - 我会更新我的答案。
    • 那个库看起来很吸引人。自 1 月 5 日以来,您没有发现任何错误吗? (谢谢!)
    • 我自己没有大量使用过,很抱歉。
    【解决方案2】:

    问题是:

    1. 每次访问 many.few 都会触发数据库查找吗?是的。不确定是 1 次还是 2 次调用
    2. 如果是,是否可以在某处缓存,因为每次只需一次查找就足以带来相同的实体?您应该能够使用 memcache 存储库来执行此操作。这在 google.appengine.api.memcache 包中。

    memcache 的详细信息在http://code.google.com/appengine/docs/python/memcache/usingmemcache.html

    【讨论】:

    • 感谢 AutomatedTester。我知道 memcache,但是当我通过引用调用另一个实体时,我不确定如何“注入它”。
    • 双重检查:在任何情况下,memcache 都没有用,因为我需要在执行中进行缓存,而不是在它们之间。使用 memcache 无助于优化此调用(它会使其更慢):(
    • 实际上,memcache 提取比数据存储区提取花费的时间更少 - 所以它仍然会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-16
    相关资源
    最近更新 更多