【问题标题】:Facebook "like" data structureFacebook“点赞”数据结构
【发布时间】:2011-11-21 04:42:15
【问题描述】:

我一直想知道 facebook 如何为您可以“喜欢”的所有不同事物管理数据库设计。如果只有一件事值得喜欢,这很简单,只是你喜欢什么的外键和你是谁的外键。

但必须有数百个不同的表可以在 facebook 上“点赞”。他们如何存储喜欢的?

【问题讨论】:

    标签: facebook database-design facebook-like


    【解决方案1】:

    如果您想在关系数据库中表示这种结构,那么您需要使用通常称为表继承的层次结构。在表继承中,您有一个定义 parent 类型的表,然后是 child 表,其主键也是返回到父级的外键。

    使用 Facebook 示例,您可能会遇到这样的情况:

    User
    ------------
    UserId (PK)
    
    Item
    -------------
    ItemId (PK)
    ItemType (discriminator column)
    OwnerId (FK to User)
    
    Status
    ------------
    ItemId (PK, FK to Item)
    StatusText 
    
    RelationshipUpdate
    ------------------
    ItemId (PK, FK to Item)
    RelationshipStatus
    RelationTo (FK to User)
    
    Like
    ------------
    OwnerId (FK to User)
    ItemId (FK to Item)
    Compound PK of OwnerId, ItemId
    

    在兴趣完整性方面,值得注意的是,Facebook 并未将 RDBMS 用于此类事情。他们为这种存储选择了 NoSQL 解决方案。然而,这是在 RDBMS 中存储此类松散耦合信息的一种方式。

    【讨论】:

    • 这可能是一个解决方案,我认为问题在于“everyhing”必须是一个“项目”,因为如果你有一个不是项目的表并且有一天你想要一个这样的表会发生什么也?。我觉得有时候越简单越好,为什么不做相反的继承呢? like 是父级,并且您有一个 like_for_status 表,其中包含一个 FK to status 和 like_for_photo 等。您可以轻松地将其扩展到任何表,并且您的查询也更快。
    • @Yuck:是的,TPT(而不是 Table-Per-Hierarchy),但据我所知,TPT 和 TPH 是实体框架词典的一部分,而不是更通用的 SQL。
    • @Enrique 是的,这当然是一个考虑因素。不过,我对“查询也更快”的说法有点怀疑。
    • @Adam Robinson,关于性能,是的,你是对的,没有太大区别,也不是选择一种或另一种方法的理由。更重要的是,根据具体情况,您的解决方案中的查询可能会更快,因为如果您知道 ItemId,则不需要 JOIN。
    【解决方案2】:

    Facebook 没有传统的外键等,因为他们的大部分数据存储不使用关系数据库。简而言之,他们不会为此而削减它。

    但是他们使用了几种 NoSQL 类型的数据存储。 “Like”很可能是基于服务,可能在整个基础设施中以 SOA 风格的方式设置的。这样,“喜欢”基本上可以归因于他们希望与之相关的任何事物。所有这一切,都具有巨大的可扩展性,并且无需处理紧密耦合的关系问题。 Facebook 无法以他们的运营量处理的事情。

    他们也可以使用 AOP(面向方面​​编程)风格的处理机制来“附加”一个“喜欢”到任何在页面呈现时可能需要一个的东西,但我认为这是通过 JavaScript 异步处理针对SOA 风格的 Web 服务或其他交付机制。

    不管怎样,我很想听听他们自己是如何从架构的角度来进行这种设置的。考虑到它们的数量,即使是简单的“Like”按钮也成为一项重要的技术实现。

    【讨论】:

    • -1。 “他们不为此而削减它”是一个意见问题和很多猜测。这个答案中唯一真正解决问题的部分(如何存储这些东西)是你的第二段。
    • +1 @adam,简单的技术事实,不涉及任何意见。 RDBMS 专为不同的使用模型而设计。
    • 就像@StephanEggermont 说亚当他们是为了不同的模型,不同的目的,Facebook 需要更多。我不是在猜测,一般数据库社区和科学界都同意。这就是存在其他解决方案的原因。 #justsayin 至于您上面的断言,键没有以这种方式对齐。这是一种适用于 RDBMS 的方式,但 RDBMS 无法提供或处理 Facebook 处理的数据。 Facebook 并没有因为他们想写其他东西而尝试放弃 RDBMS。
    【解决方案3】:

    您可以有一个带有 Id、ForeignId 和 Type 的表。类型可以是照片、状态、事件等任何东西…… ForeignId 将是表类型中记录的 id。这使得 cmets 和 likes 都成为可能。你只需要一张表来放所有的赞,一张放所有的 cmets 和我描述的那张。

    例子:

    Items
    Id  | Foreign Id  | Type
    ----+-------------+--------
      1 |         322 | Photo
      4 |         346 | Status
    
    Likes
    Id  | User Id     | Item Id
    ----+-------------+--------
      1 |         111 | 1
    

    在这里,ID 为 111 的用户喜欢 ID 为 322 的照片。


    注意:我假设您使用的是 RDBMS,但请参阅 Adron 的回答。 Facebook 确实对其大部分数据使用 RDBMS。

    【讨论】:

    • 但是你不能在“Foreign Id”中使用约束
    • @Enrique 你能详细说明一下吗?对于仅使用 RI 约束在表继承模式中可以强制执行和不可以强制执行的内容肯定存在限制,但不清楚您在说什么。
    • @Adam Robinson “Items”表中的“Foreign_Id”列不是真正的 FK,因为您不能将它指向任何表,因为它实际上指向许多表(取决于“类型”列),因此您不能在其中放置 FK(因此是约束)。这可能会使您的数据不一致。
    • @Enrique 我现在看到了......我误读了他的答案,因为它实际上并不代表表继承模式。表继承意味着您的PhotoStatus 表的主键也是返回Item 的外键。
    【解决方案4】:

    我很确定 Facebook 不会像其他人使用 RDBMS 建议的那样存储“喜欢”信息。拥有数百万用户,可能还有数千个赞,我们正在考虑加入数千行,这会影响性能。

    这里最好的方法是将所有“喜欢”附加在一行中。例如,具有文本数据类型的 user_like_id 列的表。然后附加所有喜欢该帖子的ID。在这种情况下,您只需查询一行即可获得所有信息。这将比加入表格和获取计数要快得多。

    编辑:我最近没来过这个网站,我刚刚发现这个答案被否决了。好吧,这是一个example post with like count and their avatars。这是我的设计,我刚刚实现了我所说的。

    这里的两个组件是 1.) XREF 表和 2.) JSON 对象。

    喜欢的内容仍存储在 XREF 表中。但同时,数据会附加在 JSON 对象上,并存储在 post 表的文本列中。

    为什么我将文本列中的点赞信息存储为 JSON?这样就不需要为喜欢做数据库查找/加入。如果有人与帖子不同,则 JSON 对象将被更新。

    现在我不知道为什么这里的一些用户不赞成这个答案。这个答案提供了快速的数据检索。这接近 NoSQL 方法,这是 FB 访问数据的方式。在这种情况下,不需要额外的连接/查找来获取喜欢的信息。

    这是容纳喜欢的表格。这只是用户和项目表之间的简单外部参照映射。

    【讨论】:

    • 那么你怎么知道“有多少人喜欢这个”?查询用户表中的所有行?
    • 也忘了逗号惩罚
    • @Wint 我编辑了我的答案。基本上,您仍然有一个存储喜欢的事务表。但除此之外,还有一个文本列将在该 post 表上保存一个 JSON 对象。这将保存每个帖子的类似信息。这是为了避免数据库查找。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多