在Google App Engine数据存储区中,使用父键会在多大程度上损害性能?

时间:2014-07-31 19:24:34

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

我有两个自然存在于亲子关系中的模型。子项的ID在单个父项的上下文中是唯一的,但不一定是全局的,每当我想查询特定的子项时,我都会为父项和子项提供ID。

我可以通过这两种方式实现。

  1. 将每个子实体的数据存储区键名称设为字符串“< parent_id>,< child_id>”,并进行连接和拆分以处理ID。

  2. 使用父键。

  3. 从代码角度看,选项2听起来像是明显的胜利者,但它会不会影响写入的性能?如果我从不使用事务,那么对同一父项的不同子项的并发写入是否还有开销?数据存储是否足够聪明,如果我在同一个实体组中进行了两次不能相互影响的事务,那么它们是否仍应适用?或者如果不需要锁定,是否应避免使用父键?

3 个答案:

答案 0 :(得分:2)

就数据存储本身而言,父/子关系仅是概念性的。也就是说,实际的实体没有以任何方式加入。

密钥由父密钥,种类和Id组成。这是他们之间的唯一联系。

因此,除了在事务上做事的能力之外,没有任何实际影响。同样地,兄弟姐妹没有实际的关系,只是一个概念上的关系。

例如,您可以将实体放入引用实际不存在的父级的数据存储区中。这完全合法,而且往往非常有用。

因此,选项1和选项2之间的唯一区别在于,对于选项1,您必须执行更多繁重工作,并且无法利用事务或强一致性查询。

编辑:以上几点没有提到每个实体组每秒写入1次的限制。因此,要直接回答原始问题,如果要在单个事务外的一秒内写入共享相同父键的许多实体,则使用父键限制吞吐量。

答案 1 :(得分:2)

答案 2 :(得分:1)

通常,如果您不需要在同一事务中更新或读取两个实体,则它们不应位于同一实体组中,即在其关键路径中具有相似的根,就像它们是另一个的关键父母。如果它们位于同一实体组中,则对任一实体的并发更新将争用整个组,并且可能需要重试某些更新。

从您的问题来看,听起来“<parent_id>,<child_id>”是孩子的合适的关键名称。如果您需要单独访问这些ID(例如获取具有特定“<child_id>”的所有实体),您可以将它们存储为索引属性,并根据需要执行查询。