问题 Google App Engine数据存储区中的批量更新


在Google App Engine数据存储区中对实体执行批量更新的正确方法是什么?可以在不必检索实体的情况下完成吗?

例如,在SQL中,GAE等同于这样的东西:

UPDATE dbo.authors
SET    city = replace(city, 'Salt', 'Olympic')
WHERE  city LIKE 'Salt%';

2882
2017-11-19 20:10


起源



答案:


没有直接的翻译。数据存储区确实没有更新的概念;您所能做的就是用同一地址(密钥)的新实体覆盖旧实体。要更改实体,您必须从数据存储区中获取它,在本地修改它,然后将其保存回来。

也没有与LIKE运算符等效的东西。虽然可以通过一些技巧进行通配符后缀匹配,但如果要匹配'%Salt%',则必须将每个实体读入内存并在本地进行字符串比较。

所以它不会像SQL一样干净或高效。这是对大多数分布式对象存储的权衡,数据存储也不例外。

那说, 映射器库 可用于促进此类批量更新。按照示例并使用类似的东西为您的 process 功能:

def process(entity):
  if entity.city.startswith('Salt'):
    entity.city = entity.city.replace('Salt', 'Olympic')
    yield op.db.Put(entity)

除了mapper之外还有其他选择。最重要的优化提示是批量更新;不要单独保存每个更新的实体。如果使用mapper和yield puts,则会自动处理。


9
2017-11-19 22:11



Drew-非常感谢mapper的引用 - 看起来像是我想要了解的东西。 - Yarin


答案:


没有直接的翻译。数据存储区确实没有更新的概念;您所能做的就是用同一地址(密钥)的新实体覆盖旧实体。要更改实体,您必须从数据存储区中获取它,在本地修改它,然后将其保存回来。

也没有与LIKE运算符等效的东西。虽然可以通过一些技巧进行通配符后缀匹配,但如果要匹配'%Salt%',则必须将每个实体读入内存并在本地进行字符串比较。

所以它不会像SQL一样干净或高效。这是对大多数分布式对象存储的权衡,数据存储也不例外。

那说, 映射器库 可用于促进此类批量更新。按照示例并使用类似的东西为您的 process 功能:

def process(entity):
  if entity.city.startswith('Salt'):
    entity.city = entity.city.replace('Salt', 'Olympic')
    yield op.db.Put(entity)

除了mapper之外还有其他选择。最重要的优化提示是批量更新;不要单独保存每个更新的实体。如果使用mapper和yield puts,则会自动处理。


9
2017-11-19 22:11



Drew-非常感谢mapper的引用 - 看起来像是我想要了解的东西。 - Yarin


不,没有检索实体就无法完成。

没有“1000最大记录限制”这样的东西,但任何一个请求当然都有超时 - 如果你有大量的实体要修改,一个简单的迭代可能会违反这一点。你可以通过将它分成多个操作并跟踪一个来管理它 查询游标,或者可能通过使用 MapReduce框架


5
2017-11-19 22:45



丹尼尔谢谢 - 可以宣誓,他们有一个最大记录限制 - 他们是否摆脱了它? - Yarin
在我的情况下,我本身没有得到“超时”,我得到了具体的错误: While handling this request, the process that handled this request was found to be using too much memory and was terminated. - The Red Pea
请允许我强调MapReduce旨在至少解决“两个”“太多记忆”的问题(又名 大)和“超时”(又名 长期运行): It is useful for large, long-running jobs that cannot be handled within the scope of a single request, tasks like: - The Red Pea


你可以使用查询类, http://code.google.com/appengine/docs/python/datastore/queryclass.html

 query = authors.all().filter('city >', 'Salt').fetch()
 for record in query:
   record.city = record.city.replace('Salt','Olympic')

2
2017-11-19 20:21



谢谢,但这不是将所有对象带入内存,还受到1000个最大记录限制的限制吗? - Yarin