【问题标题】:Most efficient way to delete ndb query results删除ndb查询结果的最有效方法
【发布时间】:2014-12-22 21:00:31
【问题描述】:

这是我目前的方法:

def delete_up_to_10000(query):
    for i in range(10):
        keys = query.fetch(1000, keys_only=True, deadline=40, batch_size=1000)
        ndb.delete_multi(keys)

我的问题是,是否可以在不实际获取键的情况下删除查询结果?这不应该是可能的吗?

以下是围绕我当前解决方案的几个决策点:

  • 我决定一次不超过 1000 个以减少内存使用量。
  • 我在各种 CRON 任务中每分钟调用此方法几次。
  • 根据数据的年龄和数据类型,我对可以安全删除的数据进行了某些查询 - 我目前有数十亿个实体。
  • 我希望几年后,数据的清除速度仍会比写入数据存储区的速度更快 - 因此将删除速度设置为当前写入速度的 100 倍左右。李>

【问题讨论】:

  • keys only 查询的结果是keys。
  • 是的 - 但对我来说似乎仍然需要向 megastore / bigtable 询问密钥列表,然后告诉 megastore / bigtable 删除这些项目 - 似乎我可以节省一些网络告诉 megastore / bigtable 删除它从查询中找到的任何内容,而不是报告回来
  • 考虑在每次循环中使用delete_multi_async - 将所有生成的Futures 保存在一个列表中,并在循环之后将Future.wait_all 保存在它们上(如果你甚至需要它!-)。它应该会提高您的吞吐量。
  • 谢谢@AlexMartelli 我已经切换到 fetch_page 虽然我可以使用 _async 版本 - 我认为同步版本的吞吐量应该没问题。我已将我当前的解决方案放在下面的答案中。

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


【解决方案1】:

仅键查询不检索实体。它会查看索引,但只会查看您在查询中指定的索引。

另一方面,“删除”操作不仅必须删除实体本身,还必须删除该实体的每个索引中的条目 - 无论是属性索引还是复合索引。

因此,查询根本没有同时执行删除操作所需的所有信息。假设的“删除你找到的东西”操作将只是“查找键列表,然后使用这些键更新所有索引并删除实体本身”的简写。”它可能会减少一些开销,但代价是更复杂。

【讨论】:

  • 谢谢安德烈 - 这很有道理。
【解决方案2】:

您需要获取密钥才能进行删除。您是否正在尝试批量删除并只是将其传播出去?您应该研究一个映射器(即 mapreduce)。它非常适合浏览大量数据存储条目并删除。您可以每天/每周运行一次地图作业,以控制您的数据。

【讨论】:

  • 还有内置的数据存储管理工具,可以让您轻松删除所有实体。
【解决方案3】:

这是我现在的解决方案:

def _delete_from_query(query, limit, batch_size=2000):
    delete_count = 0
    next_curs = None
    while True:
        lim = min(batch_size, limit - delete_count)
        keys, next_curs, more = query.fetch_page(
            lim, start_cursor=next_curs, deadline=40, batch_size=lim, keys_only=True
        )
        ndb.delete_multi(keys)
        delete_count += len(keys)
        if not keys or not more or delete_count == limit:
            break
    return delete_count

【讨论】:

  • 我使用相同/相似的解决方案。我不确定是否保证 fetch_page 在删除上一批结果后会返回正确的页面。例如。如果 batch_size = 10,在删除前 10 个键后,我会得到接下来的 10 个键还是会在删除后发生新的分页?我在测试解决方案时没有发现任何问题,只是想知道 fetch_page 是如何工作的,它是否预先确定了要在哪个页面上获取哪些键?
  • 与简单的python问题相比:如果我们有100个元素的列表并且想要以10个元素为一组返回它们,那么在删除前10个之后,列表的其余部分向左移动,因此,如果我删除:l[:10],然后删除 l[10:20],实际上会删除 20:30,而不是 10:20,因为移动......似乎我不会在这里遇到这样的问题,但只是想知道是否在某处记录了 fetch_page 在删除/添加满足查询条件的项目时如何工作......
猜你喜欢
  • 2014-09-30
  • 1970-01-01
  • 1970-01-01
  • 2013-12-07
  • 2012-08-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
  • 2021-04-07
相关资源
最近更新 更多