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

Mysql 优化大表上的日期范围搜索,mysql,openfire,Mysql,Openfire,我有一个聊天信息表,它的行数已经超过400万行 我需要在某个日期范围内获得发送给用户和来自用户的消息 起初,这个查询还可以,但根据表的当前大小,它花费的时间太长(>10s) 我尝试过创建许多索引组合;MySQL在messageType+sentDate上使用复合索引 SELECT `ofMessageArchive`.* FROM `ofMessageArchive` WHERE `ofMessageArchive`.`messageType` IN ('Message') AND (ofMes

我有一个聊天信息表,它的行数已经超过400万行

我需要在某个日期范围内获得发送给用户和来自用户的消息

起初,这个查询还可以,但根据表的当前大小,它花费的时间太长(>10s)

我尝试过创建许多索引组合;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
你知道我如何优化这个查询吗

[编辑]
解释
结果:

+----+-------------+------------------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+---------+-------+--------+-------------+
| 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 |
+----+-------------+------------------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+---------+-------+--------+-------------+

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

如果您还没有,请创建messageagerchive(fromJID、messageType、sentDate)的索引
messageachive的
(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

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

如果您还没有,请创建messageagerchive(fromJID、messageType、sentDate)的索引
messageachive的
(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

请提供此查询添加的解释结果的
EXPLAIN
结果请提供此查询添加的解释结果的
EXPLAIN
结果