App Engine数据存储区:实体设计和查询优化

时间:2012-04-02 12:35:46

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

我有一个系统,用户可以在实体上投票,如果他们喜欢或讨厌他们。希望在未来的某个时间,这将是数十亿票和创纪录的记录:)

目前我在这样的实体中存储投票:

UserRecordVote: recordId, userId, hateOrLike

当我想获得用户喜欢的每条记录时,我会做这样的查询:

我在“UserRecordVote”表中查询所有“喜欢”,然后我从该结果集中获取recordIds,创建该属性的一个键并从记录表中获取记录。

然后我聚合列表中的所有内容并将其返回。

以下是问题:

我想出了一个不同的方法,我想知道那个是1更快,2。成本差异是多少。

我会创建一个名为userId +“likes”的实体,密钥将是记录ID:

new Entity(userId + "likes", recordId)

因此,当我进行查询以获得所有喜欢时,我可以简单地查询所有,不需要过滤器。我可以抓住实体密钥!如果我记得app引擎的文档权利会更便宜。 (找不到定价页面了)。然后我可以使用Iterable键并进行单次获取(Iterable键)。好的,我想这种方法更快更便宜吧?但是,如果我想获取用户的所有投票或更好地说,我想抓住用户尚未投票的所有记录。

这是真正的问题:

我不想加载用户尚未投票的所有记录: 所以我会有这样的实体:

new Entity(userId+"likes", recordId);

new Entity(userId+"hates", recordId);

我会查询所有实体键的两个投票表,并查询所有实体键的记录表。然后我会删除所有匹配其中一个投票实体密钥的记录实体密钥,结果我将得到(可迭代密钥)完整实体,并且所有记录都不在两个投票表之一中。

这是一种有用的方法吗?这是执行数据存储区查询的最快且最具成本效益的方法吗?我完全错了,我应该将信息存储为列表属性吗?

编辑: 通过这种方法,我将为每个用户提供2个实体组,这将产生数百万个不同的实体组,GAE数据存储区将如何处理?至少数据存储区查看器实体选择框可能会崩溃:)?

2 个答案:

答案 0 :(得分:1)

要回答真实问题,您可能希望让hateOrLike字段存储一个表示仇恨/喜欢/未投票的整数。然后你可以过滤hateOrLike = notVoted。

您使用动态命名实体建议的其他解决方案使您无法查询实体的其他方面,因为您不知道他们的名字。

另一件事是你期望这是巨大的,你可能希望保持一个运行的投票计数器,而不是每次你拉出一个UserRecord制表 - 查询所有的投票,然后在每个视图上计算它们是非常的慢 - 特别是因为App Engine每次查询只返回1000个结果,如果你有超过1000个投票,你将不得不继续重复查询以获得所有结果。

如果您认为人们会快速投票,您应该考虑使用分片计数器来提高性能。如果您进行谷歌搜索,可以使用代码进行示例。

答案 1 :(得分:0)

考虑在实体内部的两个单独的TextProperties中序列化用户仇恨/类似投票。使用userId作为key_name。

rec = UserRecordVote.get_by_key_name(userId)
hates = len(rec.hates.split('_'))
etc.