mysql - 优化大表上的日期范围搜索

标签 mysql openfire

我有一个聊天消息表,该表已增长到超过 400 万行。

我需要在特定日期范围内接收发送给用户和接收自用户的消息。

一开始这个查询没问题,但以当前表的大小,它花费的时间太长了(>10 秒)。

我试过创建很多索引组合; MySQL 在 messageType+sentDate 上使用复合索引

SELECT `ofMessageArchive`.*
FROM `ofMessageArchive`
WHERE `ofMessageArchive`.`messageType` IN ('Message')
AND (ofMessageArchive.fromJID = 'user@example.com' OR ofMessageArchive.toJID = 'user@example.com')
AND (ofMessageArchive.sentDate > '1462235333109') 
ORDER BY ofMessageArchive.sentDate ASC LIMIT 50

我有什么想法可以优化这个查询吗?

[EDIT] EXPLAIN 结果:

+----+-------------+------------------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+---------+-------+--------+-------------+
| id | select_type | table            | type | possible_keys                                                                                                                                                                                       | key                    | key_len | ref   | rows   | Extra       |
+----+-------------+------------------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+---------+-------+--------+-------------+
|  1 | SIMPLE      | ofMessageArchive | ref  | index_ofMessageArchive_on_fromJID_and_toJID,index_ofMessageArchive_on_sentDate,index_ofMessageArchive_on_messageType,idxMessageTypeSentDate,ofMessageArchive_fromjid_idx,ofMessageArchive_tojid_idx | idxMessageTypeSentDate | 767     | const | 731570 | Using where |
+----+-------------+------------------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+---------+-------+--------+-------------+

最佳答案

您遇到了将传出消息与传入消息区别对待的问题(基本上是规范化问题),因此您不能直接在用户名上使用索引,这可能是您最重要的值(value)。

如果您还没有它们,请创建索引 ofMessageArchive(fromJID, messageType, sentDate)ofMessageArchive(toJID, messageType, sentDate)(可能顺序不同,具体取决于您对每一列有多少不同的值以及您使用的其他查询,但从这个顺序开始)。

要使用这些索引,请使用union:

select * from     
( (SELECT `ofMessageArchive`.*
   FROM `ofMessageArchive`
   WHERE (ofMessageArchive.fromJID = 'user@example.com')
   AND `ofMessageArchive`.`messageType` IN ('Message')
   AND (ofMessageArchive.sentDate > '1462235333109') 
   ORDER BY ofMessageArchive.sentDate ASC LIMIT 50
  ) union
  (SELECT `ofMessageArchive`.*
   FROM `ofMessageArchive`
   WHERE (ofMessageArchive.toJID = 'user@example.com')
   AND `ofMessageArchive`.`messageType` IN ('Message')
   AND (ofMessageArchive.sentDate > '1462235333109') 
   ORDER BY ofMessageArchive.sentDate ASC LIMIT 50
  )
) s
order by s.sentDate ASC LIMIT 50

关于mysql - 优化大表上的日期范围搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39244124/

相关文章:

mysql - 输入数据时出现 SQL 语法错误

mysql - symfony 学说自动增量迁移插入列数不匹配

android - 如何使用 asmack android 从 Openfire 检索一对一的聊天记录

android - openfire可以和mysql服务器合并吗

XMPP:Smack 客户端未收到聊天消息

mysql - 尝试比较 2 个具有多个连接的表

php - 如何通过php中的复选框删除多行

mysql - MySQL 用一个命令更新两个表

java - 如何在XMPP(Openfire)中删除群聊消息?

android - 在 Android 中获取 XMPP Open Fire 私有(private)聊天历史和消息存档