Google App Engine Datastore 中的索引和索引条目限制

Posted

技术标签:

【中文标题】Google App Engine Datastore 中的索引和索引条目限制【英文标题】:Indexes and indexes entries limits in Google App Engine Datastore 【发布时间】:2015-03-22 15:41:22 【问题描述】:

我在理解 GAE 数据存储区中的索引如何工作时遇到了一些问题,特别是对我来说真正不清楚的是与索引相关的限制。 据我了解,可以在 datastore-indexes.xml 文件中创建一些自定义索引,此外,Datastore 将生成一些自动索引以匹配用户查询。 第一个问题是:配额页面 (https://cloud.google.com/appengine/docs/quotas#Datastore) 中定义的“索引数量”配额限制仅适用于 datastore-indexes.xml 中定义的自定义索引,还是也适用于自动生成的索引?

另一个让我难以理解的概念是“单个查询的索引条目”。 假设我没有多维属性(即没有列表)并且我有一些“KindA”类型的实体。然后我定义了两组实体属性: - Group1:具有任意名称和布尔值的属性 - Group2:具有任意名称和双值的属性

在我的世界中,任何 KindA 实体最多可以具有 Group1 的 N 个属性和 Group2 的 N 个属性。对于任何属性 P,都会创建一个索引表,并且每个具有该 P 集的实体都将在 P 索引表中添加一行(对吗?)。因此,最初任何 KindA 实体对于每个最大值都有 1 个条目。 2N 个属性(因此每个实体总共最多 2N 个索引条目)对吗? 如果这是正确的,那么我可以创建一个具有有限数量属性的实体,但这很奇怪,因为我一直读到一个实体可以有无限的属性......(不考虑大小限制)。 但是,现在假设我的应用程序允许用户使用对 Group1 属性(布尔值)的任意长的 AND 过滤器序列来查询 KindA 实体。因此可以查询如下内容:

find all entities in KindA where prop1=true AND prop2=true ... AND propM = true  

在这种情况下,查询仅包含等式,因此不需要自定义索引 (https://cloud.google.com/appengine/docs/python/datastore/indexes#Index_configuration)。

但是如果我想使用 GroupB 的属性来订购呢?在这种情况下,我需要任何不同查询权限的索引(在过滤属性名称的组合方面不同)? 在我的developmnet 服务器中,我尝试不指定任何自定义索引,GAE 为我生成它们(但是任何时候我重新启动以前生成的索引都会被删除)。在这种情况下,一个单一的 KindA 实体在单个查询索引中有多少个索引条目?我说 1 是因为 GAE 文档所说的:

该属性也可能包含在您的索引配置文件 (index.yaml) 中声明的其他自定义索引中。如果一个实体没有列表属性,那么它在每个这样的自定义索引中最多有一个条目(对于非祖先索引)或对于实体的每个祖先(对于祖先索引)最多有一个条目

因此,理论上如果 N 是有限的,我对“实体的最大索引条目数”(https://cloud.google.com/appengine/docs/java/datastore/#Java_Quotas_and_limits)是安全的,对吗?

但是接收超过 200 个不同的查询呢?它是否会导致 GAE 自动生成 200 多个自定义索引(一个用于不同的查询)?如果是,这些索引是否会自动生成影响索引数量限制(即 200)? 如果是,那么我不能让用户这样做(恕我直言,非常基本)查询。我是不是误会了什么?

【问题讨论】:

看一看:***.com/questions/26751944/gae-datastore-index-limit/… 【参考方案1】:

首先,我试图理解你的问题,我觉得很难理解。

200 个索引限制仅计入您(或由 devappserver 自动为您定义的)使用查询定义的索引。这意味着将为您的索引属性单独创建的索引不计入此限制。

您在为每个索引属性创建的 2N 个自动索引中是正确的。

只要不超过每个实体 1MB 的限制,您就可以在任何实体中索引任意数量的属性。但是..这真的取决于存储的属性的内容。

对于在您的索引属性上为您创建的索引...您并没有真正的限制,而是增加成本,因为每个添加的属性都会增加每个实体的写入和存储。

使用排序顺序时,使用自动索引时您只能使用一种排序顺序。更多排序顺序将需要复合索引(您的自定义索引)。因此,如果您已经在使用相等过滤器,则无论如何都需要自定义索引。

所以,是的,在您的示例中,devapp 服务器将为您将执行的每个查询创建一个复合索引。但是,您可以通过删除不需要的索引来手动减少此索引。查询计划器可以使用查询时间通过合并不同的索引来查找结果,如下所述:

https://cloud.google.com/appengine/articles/indexselection

是的,您的 index.yaml 中的每个索引定义都将计入 200 个限制。

我发现,当您知道如何对 gae 应用程序进行编程时,您确实不会过多地使用复合索引。您需要平衡用户需要做什么和不需要做什么。还要在查询端工作之间取得平衡,或者只是查询全部并按代码过滤(这实际上取决于您可以在该特定类型中拥有多少个最大实体)。

但是,如果您尝试执行一些可供用户使用的复杂查询,那么数据存储区可能不是您的选择。

【讨论】:

感谢您的回复。实际上,我要做的是对加权标签关系进行建模。我必须通过最大 N 个标签来标记 KindA 实体,然后仅检索与用户查询的给定标签集(在 AND 中)匹配的那些实体。因此,我认为一种方法是:在编写任何 KindA 实体时,为每个主题标签(布尔值)定义一个属性,并为与主题标签关联的每个权重定义一个属性(双精度)。这样,我可以通过过滤主题标签的存在并按重量排序来获得匹配的实体。但根据你所说的这个模型,我只能通过标签过滤,而不是.. ...不是按重量排序吗?现在我找不到更好的方法来模拟这个。你能提出一些建议吗?附言。我没有创建任何自定义索引,GAE 会自动执行 ps2:你确定我可以按 AND 中的 N 个等式过滤并按 1 个属性排序,而无需让 GAE 定义复合索引吗? 我尝试分两次启动 500 个随机查询,每次 250 个。数据存储区创建了 500 个索引,但它没有抛出任何异常并执行了所有查询......对于上面所说的,它不应该超过 200 个限制吗? Gae 为你做自定义索引,但你可以自己更改索引或创建更新的索引。如“indexselection”文档中所述,您可以使用 zig-zap-merge-join 算法来降低索引计数(并增加查询执行时间)。 按 AND 中的 N 等式过滤并按 1 属性排序实际上需要自定义索引。抱歉,如果我没有正确解释。

以上是关于Google App Engine Datastore 中的索引和索引条目限制的主要内容,如果未能解决你的问题,请参考以下文章

Google Cloud 中的 Google Compute Engine、App Engine 和 Container Engine 有啥区别?

连接 Google App Engine 和 Google Compute Engine

Google App Engine Flexible 和 Google Container Engine 之间的区别?

如何在 Google Cloud App Engine 上使用 PubSub 创建订阅者,该订阅者通过 Publisher 从 Google Cloud App Engine Flex 收听消息?

将 Meteor 部署到 Google App Engine 2017

Google BigQuery 的 Google App Engine 授权