MySQL 按外键分区

MySQL partition by foreign key

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

'users' table

user_id(PK), user_name

'chat' table

chat_id(PK),user1_id(FK),user2_id(FK)

'messages' table

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

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

进行分区

我认为你可以使用 1 table 用于 聊天 table 消息 table 因为这种管理机制比你的方式好

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

我使用聊天 table 与 room_id、sender_id、receiver_id、message_text、message_date、看到的字段。而且更容易管理...

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

关于 PARTITIONing 的主要理解是它 本身提供任何性能优势。

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

如果您打算删除 "old" 个聊天记录,比如 30 天后,那么 DELETE 可以通过使用 DROP PARTITION.

来提高效率

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

回到你的具体问题:

"each chat between two users I get a partition" -- 不!分区不能很好地扩展。一般来说,数据库引擎被设计成在做 DML 事情时高效:select/insert/delete/update,但以牺牲 DDL 事情为代价:create/alter/drop.

"all of them belong to the same chat" -- 这听起来像是在尝试帮助 "caching"。其中大部分可以通过仔细选择索引来实现。给定 chatmessages 可以 "clustered" 连同 messages table 中的此技术:

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;

在几乎所有情况下,用于分区的 'purpose' 都可以通过 suitable 索引方案来模拟。 (推论:切换 to/from 分区时必须重新设计索引。)

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