GAE 数据存储索引与规范化
GAE datastore index vs normalisation
下面 entity
在 google 应用引擎数据存储区中给出,是在 reportingIds
上定义索引更好还是定义一个只有 personId
和 reportingIds
字段?
根据我理解的文档,定义索引会导致针对数据存储区配额的操作计数增加。
下面是 GAE Go 中的实体。我的代码需要经常扫描 Person 实体。它需要将其扫描限制为至少有 1 个报告人的 Person 实体。我看到了 2 种方法。
- 通过指定过滤器在 reportingIds 和
Query
上定义索引。 - Create/Update PersonWithReporters 实体,当一个人得到一个新的报告人时。
第二种情况,我的代码需要遍历PersonWithReporters
中的所有实体,不需要构造任何index/query。我可以使用始终保证拥有最新数据的 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
}
除非 AppEngine 在 Go 中的数据存储与它在 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 上添加索引。现在您可以在此实体上创建过滤器查询,并且应该能够检索到所需的信息。
我会更担心性能而不是太担心配额限制,它们相当高。只需实施它,看看它是如何工作的,以及配额是否是您主要关心的问题。
使用单独实体的方法有两个优点。
正如您已经提到的,您不需要 index/query 所有 Person 实体。
每次 Person 得到一个新的报告人时,您将创建一个新实体,这可能比更新具有许多其他属性的 Person 实体便宜得多,其中一些可能是索引。
您使用单独实体的方法也不理想。当您使用多个值索引 属性 时,数据存储会在后台为每个值创建一个索引条目。因此,当您将 3 号报告人添加到此实体时,您必须更新 3 个索引条目而不是 1 个。
您可以通过创建一个没有属性的 Reporter 实体来进一步优化您的数据模型!每次添加新的报告人时,您都会创建此 Reporter 实体,并将 ID 设置为报告人的 ID,并使其成为代表此报告人报告对象的 Person 实体的子实体。
现在,当您需要遍历所有人员并向他们汇报时,您 运行 可以对此报告者实体进行简单查询 - 无需过滤器。此查询可以设置为 keys-only(无论如何,此实体中除了键之外什么都没有,但是 keys-only 查询的处理方式不同 - 它们基本上是免费的)。
对于此查询返回的每个实体,您检索其键,此键包含一个 ID(报告人的 ID)和一个父键,其中包含此报告人报告的人的 ID到.
下面 entity
在 google 应用引擎数据存储区中给出,是在 reportingIds
上定义索引更好还是定义一个只有 personId
和 reportingIds
字段?
根据我理解的文档,定义索引会导致针对数据存储区配额的操作计数增加。
下面是 GAE Go 中的实体。我的代码需要经常扫描 Person 实体。它需要将其扫描限制为至少有 1 个报告人的 Person 实体。我看到了 2 种方法。
- 通过指定过滤器在 reportingIds 和
Query
上定义索引。 - Create/Update PersonWithReporters 实体,当一个人得到一个新的报告人时。
PersonWithReporters
中的所有实体,不需要构造任何index/query。我可以使用始终保证拥有最新数据的 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
}
除非 AppEngine 在 Go 中的数据存储与它在 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 上添加索引。现在您可以在此实体上创建过滤器查询,并且应该能够检索到所需的信息。
我会更担心性能而不是太担心配额限制,它们相当高。只需实施它,看看它是如何工作的,以及配额是否是您主要关心的问题。
使用单独实体的方法有两个优点。
正如您已经提到的,您不需要 index/query 所有 Person 实体。
每次 Person 得到一个新的报告人时,您将创建一个新实体,这可能比更新具有许多其他属性的 Person 实体便宜得多,其中一些可能是索引。
您使用单独实体的方法也不理想。当您使用多个值索引 属性 时,数据存储会在后台为每个值创建一个索引条目。因此,当您将 3 号报告人添加到此实体时,您必须更新 3 个索引条目而不是 1 个。
您可以通过创建一个没有属性的 Reporter 实体来进一步优化您的数据模型!每次添加新的报告人时,您都会创建此 Reporter 实体,并将 ID 设置为报告人的 ID,并使其成为代表此报告人报告对象的 Person 实体的子实体。
现在,当您需要遍历所有人员并向他们汇报时,您 运行 可以对此报告者实体进行简单查询 - 无需过滤器。此查询可以设置为 keys-only(无论如何,此实体中除了键之外什么都没有,但是 keys-only 查询的处理方式不同 - 它们基本上是免费的)。
对于此查询返回的每个实体,您检索其键,此键包含一个 ID(报告人的 ID)和一个父键,其中包含此报告人报告的人的 ID到.