GAE数据存储区索引与规范化

时间:2016-01-24 14:13:06

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

在Google应用引擎数据存储区中给出以下entity,是否最好在reportingIds上定义索引或定义仅包含personIdreportingIds字段的单独实体?
根据我理解的文档,定义索引会导致数据存储配额的操作数增加。

以下是GAE Go中的实体。我的代码需要经常扫描Person实体。它需要将其扫描限制为至少有1个报告人的Person实体。我看到了两种方法。

  • 通过指定过滤器在reportingIds和Query上定义索引。
  • 当一个人获得一个新的报告人时,创建/更新PersonWithReporters实体。
在第二种情况下,我的代码需要遍历PersonWithReporters中的所有实体,而不需要构造任何索引/查询。我可以使用Key进行迭代,而Key始终保证拥有最新数据。考虑到数据存储区操作计入配额限制,不确定哪种方法是有益的。

type Person struct {
    Id string //unique person id
    //many other personal details, his personal settings etc
    reportingIds []string //ids of the Person this guy manages
}

type PersonWithReporters struct {
   Id string //Person managing reportees
   reportingIds []string //ids of the Person this guy manages
}

2 个答案:

答案 0 :(得分:1)

除非Go中的AppEngine数据存储与它在Java或Python中的工作方式非常不同,否则您无法本机索引数组 - 因此选项1是不可能的,选项2也是如此。

我建议选项三,即定义

type PersonWithReporters {
    Id string // concatenate(managing_Person_id, separator, reporter_Person_id) to avoid id collisions
    reportingId string; // indexed
    managingId string; // probably indexed as well
}

您将创建多个这些实体,而不是具有数组的单个实体。您还要在reportingId上添加索引。现在,您可以在此实体上创建过滤器查询,并且应该能够检索所需的信息。

我会更担心性能,而不是太多关于配额限制,它们非常高。只需实施它,看看它是如何工作的,以及配额是否是您的主要关注点。

答案 1 :(得分:1)

具有单独实体的方法为您提供了两个优势。

  1. 正如您已经提到的,您不需要索引/查询所有Person实体。

  2. 每当一个人获得一个新的报告人时,您将创建一个新实体,这可能比更新具有许多其他属性的Person实体便宜得多,其中一些属性可能被编入索引。

  3. 您使用单独实体的方法也不理想。当您使用多个值索引属性时,数据存储区会为每个值创建一个索引条目。因此,当您向此实体添加报告人员编号3时,您必须更新3个索引条目而不是1。

    您可以通过创建没有属性的Reporter实体来进一步优化数据模型!每次添加新的报告人员时,您都会创建此Reporter实体,其ID设置为报告人员的ID,并使其成为代表此报告人所报告的人员的Person实体的子实体。

    现在,当您需要通过向其报告的所有人进行迭代时,您可以对此Reporter实体运行简单查询 - 无过滤器。这个查询可以设置为仅限密钥(无论如何,这个实体中只有一个密钥,但是只有密钥的查询被区别对待 - 它们基本上是免费的。)

    对于此查询返回的每个实体,您都会检索其密钥,此密钥包含一个ID(一个报告人的ID)和一个父密钥,其中包含此报告者向其报告的人员的ID。