【问题标题】:Are keys-only Datastore queries that return thousands of results unavoidably slow?返回数千个结果的纯键数据存储查询是否不可避免地很慢?
【发布时间】:2022-02-04 16:17:35
【问题描述】:

我有一个使用 go115 运行时的 App Engine 应用,它通过 google.golang.org/appengine/v2/datastore 包与 Cloud Datastore 交互。该应用使用自动分配的整数 ID 和 Rating 字段(以及其他字段)插入和查询 Song 实体:

type Song struct {
    // ...
    Rating float64 `json:"rating"`
    // ...
}

对于 19,900 个 Song 实体,https://console.cloud.google.com/datastore/stats 报告的数据大小为 15.53 MB,内置索引大小为 102.27 MB,复合索引大小为 86.31 MB。该应用在us-central 中运行,而Datastore 在nam5 (us-central) 中。

从 App Engine 运行时,以下仅键查询始终需要 2-4 秒才能返回 13,571 个键:

q := datastore.NewQuery("Song").KeysOnly().Filter("Rating >=", 0.75)
keys, err := q.GetAll(ctx, nil)

使用Run 而不是GetAll 并在迭代时收集ID 似乎要快一点。我还尝试使用笔记本电脑上的cloud.google.com/go/datastore 包,以确保旧的appengine 包不是特别慢,但结果要差得多(7-9 秒)。

我的理解(基于 ​​Indexes documentthe I/O 2010 "Next gen queries" talk 之类的内容)是 Datastore 会自动维护 Rating 字段的索引。我希望使用该索引来满足这个查询是微不足道的。结果集中的整数 ID 似乎应该消耗大约 100 KB 的空间。

我还没有从 Google 那里找到任何关于从 Datastore 获得何种性能类型的官方指导,但这比我希望的要慢得多。当我通过对数据的 JSON 转储运行 jq 工具和 grep 在笔记本电脑上执行此查询的蛮力逼近时,只需要 400 毫秒。

是否预计只有键的普通数据存储区查询需要几秒钟才能返回数千个键?

当我运行返回较小结果集的仅键查询时,性能会更好:返回 300-400 个键的查询通常需要 100-200 毫秒,而返回少于 200 个键的查询在 40-70 毫秒内完成。

我无法修改我的许多查询来限制它们返回的结果数量:

我可以想到在某些情况下可能会有所帮助的技巧(例如,对我的实体进行分片/分区,以便我可以并行运行多个查询),但我希望尽可能避免这种情况。

【问题讨论】:

    标签: google-app-engine google-cloud-platform google-cloud-datastore


    【解决方案1】:

    我会说在 2-4 秒内返回 13,571 个键的仅键查询相当快。毕竟它仍然是一个查询。

    如果可能的查询总数不是很大,也许你可以提前存储查询结果?

    【讨论】:

    • 我目前将查询结果缓存在一个从查询哈希映射到结果 ID 的 Datastore 实体中,但潜在查询的数量很大,并且它们的结果经常因更新而失效。在我看来,Datastore 施加了许多限制以保证良好的性能,所以我很惊讶这个查询不需要,比如说,少于 100 毫秒——不是所有返回的键都已经存在在索引中?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 2011-04-22
    • 1970-01-01
    • 2022-01-15
    • 2016-10-05
    相关资源
    最近更新 更多