1

我目前正在使用 NDB 库将 XML 文件中的一些实体重新插入 Google Datastore。我观察到的问题是,有时ndb.put_multi()似乎没有返回,脚本挂起等待它。

代码基本上是在做以下事情:

@ndb.toplevel
def insertAll(entities):
    ndb.put_multi(entities)

entities = []
for event, case in tree:
    removeNamespace(case)
    if (case.tag == "MARKGR" and event == "end"):
        # get ndb.Model entities
        tm, app, rep = decodeTrademark(case)

        entities.append(tm)
        for app_et in app:
            entities.append(app_et)
        for rep_et in rep:
            entities.append(rep_et)
        if (len(entities) > 200):
            n_entitites += len(entities)
            insertAll(entities)
            entities = []

if(len(entities) > 0):
    insertAll(entities)

我之前已经注意到这种行为,但它似乎是非常不确定的,我想知道是否有办法正确调试和/或设置超时ndb.put_multi所以如果它在给定之后没有返回,我至少可以重试它时间。

提前致谢,

4

3 回答 3

1

原始答案(OP 编辑​​前)

你的逻辑有缺陷。 insertAll()可能永远不会被调用。在哪里app定义rep?如果它们是在这个函数之外定义的,为什么它们在嵌套循环中?任何实体rep都在获得书面len(app) * len(tree)时间!

另外,len(entities)< 200 的情况呢?那是在 3 个嵌套循环内。肯定会有迭代len(entities)小于 200 的情况。如果在所有循环之后,总数为 750,请考虑孤立实体。您将孤立 150 个实体。

至少在循环运行后附加它,以编写孤立实体(< 200):

if len(entities) > 0:
    insertAll(entities)

还可以尝试将 200 减少到更小的值,例如 100。根据实体的大小,200 可能太多而无法在超时之前完成。

您是否检查过是否写入了任何实体?

此外,您确定您了解entity数据存储所使用的 an 是什么吗?如果您只是从 XML 文件中提取字符串,那么这些不是实体。 rep并且app必须是数据存储实体的列表,并且tm必须是实际的数据存储实体。

更新:

好的,这更有意义,但是您仍然孤立了一些实体,并且无法控制put_multi(). 而不是if (len(entities) > 200):,您应该对它们进行批处理:

# primitive way to batch in groups of 100
batch_size = 100
num_full_batches = len(entities) // batch_size
remaining_count = len(entities) % batch_size

for i in range(num_full_batches):
    ndb.put_multi(entities[i * batch_size : (i+1) * batch_size])

if remaining_count > 0:
    ndb.put_multi(entities[(i+1) * batch_size:])

如果实体太多,您应该将其发送到taskqueue

于 2018-07-31T15:40:32.997 回答
1

基于Ikai Lan 的“App Engine 数据存储提示:单调递增的值是不好的”

单调递增的值是那些存储/读取/写入/严格顺序的值,例如日志中的时间戳。在当前的 Datastore 实施中,它们将在同一位置/点按顺序存储/读取/写入,并且 Datastore 将无法正确拆分工作负载。因此,当 OPS 足够高且 Datastore 无法水平增长时,您会注意到速度变慢。这称为热点

最重要的是,Datastore为每个可索引的属性创建一个索引,除了Text 属性,这意味着您可以在某个时候拥有各种热点。

解决方法

官方文档中提到的解决方法之一是为索引值添加哈希:

如果您确实有一个单调递增的键或索引属性,那么您可以预先添加一个随机散列以确保键被分片到多个平板电脑上。

阅读更多关于“窄键范围的高读/写率”

于 2018-08-07T13:54:43.743 回答
0

从您之前留下的评论来看,该应用程序似乎达到了实体读/写限制,即 1 op/s。您可以在此处阅读有关数据存储限制的更多信息。

作为替代方案,您可以尝试使用 Cloud Firestore,因为它在 Datastore 模式下使用时没有这些限制。

于 2018-08-01T14:36:10.623 回答