【问题标题】:Optimizing date range search on large table优化大表上的日期范围搜索
【发布时间】:2017-01-07 17:17:20
【问题描述】:

我有一个聊天消息表,它已经增长到超过 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

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

[编辑]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 |
+----+-------------+------------------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+---------+-------+--------+-------------+

【问题讨论】:

  • 请提供EXPLAIN本次查询的结果
  • 添加解释结果

标签: mysql openfire


【解决方案1】:

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

如果您还没有它们,请创建索引 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

【讨论】:

    猜你喜欢
    • 2023-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多