【问题标题】:Datastore efficiency, low level API数据存储效率,低级 API
【发布时间】:2016-10-25 19:32:00
【问题描述】:

每个 Cloud Datastore 查询都使用一个或多个索引来计算其结果,这些索引包含按索引属性和(可选)实体祖先指定的序列中的实体键。索引会以增量方式更新,以反映应用程序对其实体所做的任何更改,以便所有查询的正确结果都可用,而无需进一步计算。

一般情况下,我想知道

datastore.get(List<Key> listOfKeys);

比准备好索引文件的查询更快或更慢(结果相同)。

Query q = new Query("Kind")(.setFilter(someFilter));

我目前的问题:

我的数据由图层和点组成。点仅属于一个唯一的层,并且在层内具有唯一的 id。我可以通过多种方式加载这些点:

1) 具有“层名称”属性的点并使用过滤器进行查询。 - 在这里我不确定数据存储是否会准备好结果,因为图层名称会动态变化。

2) 仅使用键。该层必须存储点 ID。

KeyFactory.createKey("Layer", "layer name");
KeyFactory.createKey("Point", "layer name"+"x"+"point id");

3) 使用不带过滤器的查询:我实际上不需要通用种类“点”,可以更具体:种类将是 (“层名称”+“点 id”) - 创造更多种类的成本是多少?这可能是最快的方法吗?

您能详细了解数据存储的工作原理吗?

【问题讨论】:

    标签: google-app-engine google-cloud-datastore low-level-api


    【解决方案1】:

    比准备好索引文件的查询更快或更慢(结果相同)。

    从根本上说,查询和按键获取不能保证具有相同的结果。

    查询最终是一致的,而按键获取数据是强一致的。

    在优化速度之前,您的第一个挑战可能是确保您显示正确的数据。

    这些文档很好地解释了最终一致性与强一致性,听起来您可以选择使用可以强一致性的祖先查询。我还强烈建议避免使用“名称”——它是动态的——作为实体名称,这会给你带来过多的悲伤。

    编辑: 为了特别有用,基于您的描述的可行解决方案的一种选择是:

    1. 为每一层提供一个唯一的 id(可能是一个 uuid),将名称存储为属性
    2. 包括层键作为每个点实体的父键
    3. 在获取层的点时使用祖先查询(这是高度一致的)

    另一种选择是将点存储为嵌入式实体,并且整个层只有一个实体 - 取决于您要实现的目标。

    【讨论】:

    • 感谢您指出一致性问题。我应该包括我的图层将被编辑并显示给少数用户......我为什么要担心“名称”作为实体名称?我会阻止人们使用已使用的名称保存图层...然后我可以很容易地重新创建键。
    • 最终一致性是一个设计约束,而不是用户数量的函数。要了解其含义,请部署到应用引擎,保存并重新加载。您几乎肯定不会看到刚刚保存的积分。你需要解决这个问题。
    • 如果您使用 name 作为实体名称,rename 是新记录的放置,旧记录的删除,并且您必须更新引用该层的每个实体。这与在关系数据库中使用名称作为 pk 相同 - 它影响所有逻辑连接的实体。如果您然后尝试以事务方式执行此操作,则每个 XG 事务的限制为 25 个实体,因此使用此模型,如果层中有超过 23 个点,您将遇到问题。我向你保证,这是一种你不想面对的痛苦。
    • 哦,我明白了.. 使用这个名字真的很愚蠢:D 谢谢你解释原因!