【问题标题】:MySQL partition by foreign keyMySQL按外键分区
【发布时间】:2020-04-23 08:28:43
【问题描述】:

我在 MySQL 中有一个聊天数据库。

'用户'表

user_id(PK), 用户名

'聊天'表

chat_id(PK)、user1_id(FK)、user2_id(FK)

'消息'表

message_id(PK)、chat_id(FK)、user_from(FK)、message_text、message_date

由于我希望消息表中有数百万条记录,因此我想到了对其进行分区。这是一个好方法吗?这里必须使用什么类型的分区?我想如果我按 chat_id 分区,那么对于两个用户之间的每次聊天,我都会得到一个分区。在实践中,因此每次都会检索分区中的所有记录,因为它们都属于同一个聊天。但是,这意味着如果我有 100 万条聊天记录,我就有 100 万个分区。但是,由于chat_id 是外键,MySQL 不允许按chat_id 进行分区。

【问题讨论】:

    标签: mysql database database-design database-partitioning


    【解决方案1】:

    要了解PARTITIONing 的主要内容是它确实固有地提供任何性能优势。

    有一些例外。唯一可能适用的是:

    如果您打算删除“旧”聊天,比如 30 天后,那么使用 DROP PARTITION 可以提高 DELETE 的效率。

    更多讨论:http://mysql.rjweb.org/doc.php/partitionmaint

    回到您的具体问题:

    “两个用户之间的每次聊天我都会得到一个分区”——不!分区不能很好地扩展。一般来说,数据库引擎在做 DML 事情时被设计为高效:select/insert/delete/update,但以 DDL 事情为代价:create/alter/drop。

    “所有这些都属于同一个聊天”——这听起来像是在尝试帮助“缓存”。其中大部分可以通过仔细选择索引来实现。给定chatmessages 可以与messages 表中的此技术一起“聚集”:

    CREATE TABLE Messages (
        message_id BIGINT NOT NULL AUTO_INCREMENT,
        chat_id INT UNSIGNED NOT NULL,
        ...
        PRIMARY KEY(chat_id, message_id),  -- to cluster by chat
        INDEX(message_id)   -- to keep auto_increment happy
    ) ENGINE=InnoDB;
    

    在几乎所有情况下,分区的“目的”都可以通过合适的索引方案来模拟。 (推论:在切换到/从分区时必须重新设计索引。)

    “100 万个分区”——8K 是极限。并且,每个分区至少有一个磁盘文件;操作系统不喜欢拥有一百万个文件,尤其是在单个目录中。甚至 8K 都在拉伸。

    【讨论】:

      【解决方案2】:

      我认为聊天表消息表都可以使用一张表,因为这种管理机制比你的方式更好。

      你认为会有数百万条消息,所以你认为I can split the tables so it will be easier 但我认为这种管理很难而且没有优化!

      我使用带有 room_id、sender_id、receiver_id、message_text、message_date、seen 字段的聊天表。而且更容易管理...

      如果您认为我可以拥有数百万条消息,那么您可以使用 2 个数据库和 负载平衡,然后您可以通过进行负载平衡来检查消息和数据库。

      【讨论】:

        猜你喜欢
        • 2021-04-29
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-21
        • 2012-08-29
        相关资源
        最近更新 更多