在 Google 数据存储中,按键查询是否比索引 属性 查询更快?
Is query by key faster than query by indexed property in Google Datastore?
考虑以下数据存储实体:
public class Employee {
@Id String id;
@Index String userName
}
我的理解是,只有那些属于查询过滤条件的属性才需要用 @Index
注释。数据存储中的索引不是为了性能而是为了获取数据。
id
也要注解@Index
才能被id
查询吗?如果不是,数据存储是否自动为键创建索引?
@Id
注释确保管理唯一性,但它与索引属性相比没有性能优势。是吗?
- 在上面的例子中,
id
查询会比 userName
查询更快吗?
- 否,将自动创建
@Id
确保它是 Key
- 找不到确认信息,但必须更快。而且它比查询便宜,get 读取 1 次,query 读取 2 次。参见 https://cloud.google.com/datastore/docs/pricing
此外,请记住,如果您决定稍后添加 @Index
注释,那么它将仅为新实体创建,所有现有实体都将取消索引。这意味着您需要重新索引数据库,或者只有新记录会从带有此字段过滤器的查询中返回。
1:
不,您不需要明确索引它。 Datastore 使用您的键作为实体的主键(在 Entities table 中)。
2 & 3:
按主键查询效率更高(您只需要对主键进行一次扫描 table,而不是先对索引进行扫描,然后再在主键中进行查找 table。但是,它还允许您执行 Lookup
而不是查询:
Employee e = ofy().load().type(Employee.class).id("<id>").now();
除了避免查询计划和索引扫描来查找这个Employee
,这是Strongly Consistent。如果你不这样做,你可能会写一个新的 Employee
但当你查询它们时实际上看不到它们。
虽然 强一致性 从应用程序正确性的角度来看很重要,但它会更慢。特别是,当您进行强一致性查找时,Datastore 可能需要与其他副本(在其他数据中心)通信以 catch up your entity group.
如果您对最终一致性没问题,您可以执行具有最终一致性的 Lookup
以避免索引扫描 和 副本使用 read policy.在 objectify 中,这看起来像:
Employee e = ofy().consistency(Consistency.EVENTUAL).load()
.type(Employee.class).id("<id>).now();
注意: 这个答案谈了很多关于索引和 table 的内容。一般来说,我建议不要从索引和 table 的角度考虑 Datastore(因为它 不是 关系存储系统)。但是,它是在关系数据库上实现的,对于回答您的问题非常有用。 This page 有很好的背景。
Objectify 总是通过键获取 - 如果您 运行 查询,它只进行键查询,然后通过 ID 获取结果。这很有效,因为它具有缓存集成,并且还意味着您可以获得准确的结果(因为数据是高度一致的,即使它们查询结果不是)。您可以在查询中使用 .hybrid(boolean)
方法来控制它。
您不能通过 id 查询 - 您只能通过 key 获取。如果你想这样做,你需要一个重复的索引字段,并对其进行查询。这是密钥在数据存储区中工作方式的产物。
考虑以下数据存储实体:
public class Employee {
@Id String id;
@Index String userName
}
我的理解是,只有那些属于查询过滤条件的属性才需要用 @Index
注释。数据存储中的索引不是为了性能而是为了获取数据。
id
也要注解@Index
才能被id
查询吗?如果不是,数据存储是否自动为键创建索引?@Id
注释确保管理唯一性,但它与索引属性相比没有性能优势。是吗?- 在上面的例子中,
id
查询会比userName
查询更快吗?
- 否,将自动创建
@Id
确保它是Key
- 找不到确认信息,但必须更快。而且它比查询便宜,get 读取 1 次,query 读取 2 次。参见 https://cloud.google.com/datastore/docs/pricing
此外,请记住,如果您决定稍后添加 @Index
注释,那么它将仅为新实体创建,所有现有实体都将取消索引。这意味着您需要重新索引数据库,或者只有新记录会从带有此字段过滤器的查询中返回。
1:
不,您不需要明确索引它。 Datastore 使用您的键作为实体的主键(在 Entities table 中)。
2 & 3:
按主键查询效率更高(您只需要对主键进行一次扫描 table,而不是先对索引进行扫描,然后再在主键中进行查找 table。但是,它还允许您执行 Lookup
而不是查询:
Employee e = ofy().load().type(Employee.class).id("<id>").now();
除了避免查询计划和索引扫描来查找这个Employee
,这是Strongly Consistent。如果你不这样做,你可能会写一个新的 Employee
但当你查询它们时实际上看不到它们。
虽然 强一致性 从应用程序正确性的角度来看很重要,但它会更慢。特别是,当您进行强一致性查找时,Datastore 可能需要与其他副本(在其他数据中心)通信以 catch up your entity group.
如果您对最终一致性没问题,您可以执行具有最终一致性的 Lookup
以避免索引扫描 和 副本使用 read policy.在 objectify 中,这看起来像:
Employee e = ofy().consistency(Consistency.EVENTUAL).load()
.type(Employee.class).id("<id>).now();
注意: 这个答案谈了很多关于索引和 table 的内容。一般来说,我建议不要从索引和 table 的角度考虑 Datastore(因为它 不是 关系存储系统)。但是,它是在关系数据库上实现的,对于回答您的问题非常有用。 This page 有很好的背景。
Objectify 总是通过键获取 - 如果您 运行 查询,它只进行键查询,然后通过 ID 获取结果。这很有效,因为它具有缓存集成,并且还意味着您可以获得准确的结果(因为数据是高度一致的,即使它们查询结果不是)。您可以在查询中使用 .hybrid(boolean)
方法来控制它。
您不能通过 id 查询 - 您只能通过 key 获取。如果你想这样做,你需要一个重复的索引字段,并对其进行查询。这是密钥在数据存储区中工作方式的产物。