mysql - 如何在mysql中对一个非常大的消息表进行分区
问题描述
我有一个包含来自用户的消息的表。该设计将为发送者和接收者保留一份消息副本(每个人都有自己的消息已读/已删除标志)。
CREATE TABLE cloob_msg.cl_inbox (
id int(11) NOT NULL AUTO_INCREMENT,
`user` int(11) NOT NULL,
contact int(11) NOT NULL,
sdate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
body text NOT NULL,
userstatus tinyint(4) NOT NULL DEFAULT 1 COMMENT '0: new, 1:read, 2: deleted',
contactstatus tinyint(4) NOT NULL DEFAULT 0,
class tinyint(4) NOT NULL DEFAULT 0,
attachtype tinyint(4) NOT NULL DEFAULT 0,
attachsrc varchar(255) DEFAULT NULL,
PRIMARY KEY (id),
INDEX i_class (class),
INDEX i_contact_user (contact, user),
INDEX i_contactstatus (contactstatus),
INDEX i_user_contact (user, contact),
INDEX i_userstatus (userstatus)
)
为了列出两个人之间的对话,我们使用以下查询:
select * from cl_inbox
where (user=user1 and contact=user2 and userstatus<>2)
or (user=user2 and contact=user1 and contactstatus<>2)
order by id limit ?,?
现在,我如何对表进行分区(我们有数十亿条消息,所以它真的需要分区)?我应该选择哪些唯一键和哪些分区字段?
谢谢。
解决方案
为什么要分区?它本身不会提供任何性能。
要加快该查询,请更改or
为union
:
( select * from cl_inbox
where (user=user1 and contact=user2 and userstatus<>2)
order by id limit ?,?
) UNION ALL
( select * from cl_inbox
where (user=user2 and contact=user1 and contactstatus<>2)
order by id limit ?,?
)
现在每个部分都可以独立使用i_contact_user
or i_user_contact
。(您的版本必须进行全表扫描。)这将运行得更快。顺便说一句,对于这个查询,这两个索引同样好。除非您同时需要其他查询,否则我建议删除其中一个。(和其他“标志”)上的索引*status
可能没用,对于这个查询肯定没用。
下一个问题:OFFSET
用于分页是有问题的。当切换到 时UNION
,它现在坏了。
所以,相反,“记住你离开的地方”。既然你说order by id
,我假设 id 是 UI 所需的顺序?删除OFFSET
并使用id
:
( select * from cl_inbox
where (user=user1 and contact=user2 and userstatus<>2)
AND id < $left_off
ORDER BY id DESC
LIMIT ?
) UNION ALL
( select * from cl_inbox
where (user=user2 and contact=user1 and contactstatus<>2)
AND id < $left_off
ORDER BY id DESC
LIMIT ?
)
ORDER BY id DESC
LIMIT ?
(是的,我故意重复ORDER BY
and LIMIT
。)我冒昧地扭转了局面——你不想要最新消息吗?
更多讨论:http: //mysql.rjweb.org/doc.php/pagination
如果您希望拥有一个巨大的表,并希望删除“旧”记录,那么我们可以讨论分区以方便旧行。但这是我看到的对该表进行分区的唯一用途。
推荐阅读
- token - Remix 自动将令牌部署还原为仅地址
- node.js - 我们可以在使用 express-fileUpload 时保留以前的上传文件吗
- oracle - 如何在oracle中使用序列插入选择行组
- ios - 在平移手势处理程序中禁用滚动视图的滚动不会触发本机反应中的平移手势事件
- jenkins - Jennkins 无法连接 AWS 账户
- image-processing - 比较编辑前后的两个图像
- java - 什么导致错误****错误:运行ghostscript时为Tz提供的0.0水平文本缩放无效,我该如何解决?
- node.js - nodeJs pkg 模块执行另一个脚本
- bash - Mac OS:尝试在 bash 终端中安装 Vue.js @vue/cli 但它没有运行/找到路径
- html - CSS 按钮在 IOS 上看起来不一样