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