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"。其中大部分可以通过仔细选择索引来实现。给定 chat
的 messages
可以 "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 都在拉伸。
我在 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"。其中大部分可以通过仔细选择索引来实现。给定 chat
的 messages
可以 "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 都在拉伸。