可扩展的MySQL数据库,用于类似邮件的消息

时间:2010-02-10 10:57:09

标签: sql mysql database database-design scalability

假设我们有一个热门网站。我们需要在用户之间实现类似邮件的消息传递。 典型的解决方案是使用2个表:

用户(user_id)

消息(message_id,sender_id(引用user_id),receiver_id(引用user_id),主题,正文)。

此方法有两个显着的局限性

  1. 所有用户的所有消息都存储在一个表中,导致高负载并降低整体数据库性能。
  2. 当有人需要同时向多个用户发送邮件时,邮件会被复制(recipients_count)次。
  3. 另一个解决方案使用3个表:

    用户(USER_ID)

    已发送消息(sent_id,sender_id(引用user_id),主题,正文)

    Received_messages (sent_id,receiver_id(引用user_id),主题,正文)

    received_messages的主题和正文从sent_messages的相应字段中复制。

    此方法导致

    1. 通过将信息从一个表复制到另一个表来对数据库进行非规范化
    2. 用户实际上可以删除已发送/已接收的邮件,而无需将其从接收方/发件人中删除。
    3. 消息占用的空间大约是空间的2倍
    4. 每张桌子的装载量减少约2倍。
    5. 所以在这里提出问题:

      1. 考虑哪种设计更适合高负载和可扩展性? (我认为这是第二个)
      2. 是否有其他数据库设计可以处理高负载?它是什么?有什么限制?
      3. 谢谢!

        P.S。我知道在解决这些可扩展性问题之前,网站必须非常成功,但我想知道如果需要该怎么做。

        更新

        目前,对于第一个版本,我将使用Daniel Vassallo提出的设计。但如果将来一切正常,设计将改为第二个。感谢Evert减轻了我的担忧。

2 个答案:

答案 0 :(得分:3)

在向多个收件人发送邮件的情况下,您可能希望避免多次复制邮件正文。这是您可能需要考虑的另一个选项:

  
      
  • 用户(user_id)

  •   
  • 消息(message_id,sender_id,subject,   体)

  •   
  • received_messages (message_id,user_id,address_mode,已删除)

  •   

这种模式可能比电子邮件更像推特,但它可能带来一些优势。

规则是:

  • 邮件只能由一个用户发送,在每封邮件的sender_id中引用。
  • 每个收件人都将在received_messages表中定义。 address_mode字段可以定义消息是直接发送给收件人,还是作为CC发送,还是作为BCC发送。这个字段显然是可选的。
  • 收件人删除的邮件会在received_messages表中标记已删除的邮件。
  • 转发和回复的邮件需要使用新的sender_id重新创建。然后可以修改邮件正文。

这些是一些优点:

  • 这比原始问题中提到的两个选项占用的空间更少,特别是如果用户通常会向多个收件人发送邮件。
  • 更容易缓存消息表,因为消息永远不会重复。
  • 删除邮件的收件人不会删除邮件发送给该用户的信息。它只会在received_messages表中标记为“已删除”。
  • 您还可以获得标准化模型。

对于大多数应用程序,如果对上述模型使用乐观隔离级别,即使您希望以每秒几个的速率交换消息,也不会出现性能问题。另一方面,如果您期望每秒有数百或数千条消息,那么考虑其他选项可能就是这种情况。

答案 1 :(得分:1)

一般来说,数据库大小不会太大。速度更重要。

因此,我很想去选项二。就像你提到的那样,它使得删除消息变得更容易,而且我很确定这是一种非常常见的方法。