0

在我的应用程序中,我们需要在数据存储区中开发一个 FRIENDS 关系表。当然,我想到的一个快速解决方案是:

user     = db.ReferenceProperty(User, required=True, collection_name='user')
friend   = db.ReferenceProperty(User, required=True, collection_name='friends')

但是,当朋友列表增长到一个巨大的数字,比如几千或更多时会发生什么?这会不会太低效了?

性能始终是我们的首要任务。这是非常需要的,因为我们将没有更多的东西来遵循这种类似的关系设计。

请就在 App Engine Python 环境中使用数据存储区设计 FRIENDS 关系表的最佳方法提供建议。

EDIT 除了 FRIENDS 关系,FOLLOWER 关系也将被创建。而且我相信大多数时候所有这些关系都足以成为查询,因为我的应用程序倾向于面向社交媒体的原因。

例如,如果我关注一些用户,我将获得关于他们将要做什么等的新闻提要更新。随着时间的推移,活动会增加。至于有多少用户,我还不能回答,因为我们还没有上线。但我预计随着我们的发展,将会有数百万用户。

希望这将有助于获得更具体的建议,或者是否有替代这种方法的方法?

4

2 回答 2

1

您的 FRIENDS 模型(可能还有您的 FOLLOWERS 模型)应该可以很好地扩展。系统中最棘手的部分实际上是聚合来自用户所有朋友和关注者的内容。

由于您在帖子中描述的表格,查询用户列表是 O(N),其中 N 是朋友的数量。但是,这些查询中的每一个都需要另一个 O(N) 操作来检索朋友共享的内容。每次用户想要查看最近的内容时,这都会导致 O(N^2)。这个特定的查询不好有两个原因:

  1. 在为数百万用户设计系统时,您不想在核心算法中看到 O(N^2) 操作。
  2. App Engine 倾向于限制这些类型的查询。具体来说,IN您需要使用的关键字来获取共享项目列表不适用于超过 30 个朋友。

对于这个特殊问题,我建议创建另一个表,将每个用户链接到每个共享内容。像这样的东西:

class SharedItems(db.Model):
  user = db.ReferenceProperty(User, required=True) # logged-in user
  from = db.ReferenceProperty(User, required=True) # who shared it
  item = db.ReferenceProperty(Item, required=True) # the item itself
  posted = db.DateTimeProperty() # when it was shared

当需要渲染更新流时,您需要一个 O(N) 查询(N 是您要显示的项目数)来查找与用户共享的所有项目(按日期降序排列)。保持 N 小以使其尽可能快。

共享一个项目需要创建 O(N) SharedItems,其中 N 是发布者拥有的朋友和关注者的数量。如果这个数字太大而无法在单个请求中处理,请将其分片到任务队列或后端。

于 2012-07-14T05:09:53.817 回答
0

propertylist 是在 GAE 中获得廉价/简单索引的好方法。但正如您正确识别的那样,存在一些限制。

  1. 整个实体的索引大小是有限的(我认为目前是 5000)。所以每个 propertyList 值都需要一个索引。所以基本上属性列表大小<4999

  2. 这么大的财产清单的连载是昂贵的!带回一个 2Mb 的实体很慢……而且会消耗 CPU。

如果期望一个大的 propertyIndex 那就不要这样做。

另一种方法是创建一个对关系建模的 JOIN 表

 class Friends(db.Model):
  user = db.ReferenceProperty(User, required=True) # logged-in user
  from = db.ReferenceProperty(User, required=True) # who shared it

只是一个有 2 个键的实体。这允许简单的查询来查找用户的所有朋友。

select from friends where user = : me

找到我是朋友的所有用户。

select from friends where friend = : me

因为它返回一个密钥,你可以做一个批量 get(keylist) 来获取实际的朋友详细信息。

于 2014-03-03T06:22:42.580 回答