如何在mysql中对非常大的消息表进行分区

时间:2020-01-15 20:01:20

标签: mysql partitioning

我有一个表,其中包含来自用户的消息。该设计将为发送者和接收者保留单个消息副本(每个人都有自己的消息读取/删除标志)。

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 ?,?

现在,如何对表进行分区(我们有数十亿条消息,因此实际上需要对其进行分区)?我应该选择什么唯一键和哪些分区字段?

谢谢。

1 个答案:

答案 0 :(得分:2)

为什么要分区?它本质上不会提供任何性能。

要加快查询速度,请将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_useri_user_contact。 (您的版本必须进行全表扫描。)这将运行得更快。顺便说一句,对于该查询,这两个索引同样好。除非同时需要其他两个查询,否则建议删除其中一个。 *status上的索引(和其他“标志”)可能无用,对于该查询肯定是无用的。

下一个问题:使用OFFSET进行分页是有问题的。并且当切换到UNION时,它现在已损坏。

因此,“记住您离开的地方”。既然您说的是order by id,那么我假设ID符合用户界面所需的顺序?删除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 BYLIMIT。)而且我自由地扭转了局面–您是否不想要 latest 消息首先?

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

如果您期望有一个巨大的表,并希望删除“旧”记录,那么我们可以讨论分区以方便旧行。但这是我看到的对该表进行分区的唯一用途。

相关问题