首页 > 解决方案 > 查询时间过长且未使用索引

问题描述

我们有一个事件服务,它返回按 id 和事件时间戳过滤并按主列排序的事件。

此表中大约有 1.5 GB 的数据

询问:

SELECT event.eventID, event.orgID, event.objectType, event.action, event.objectID, 
       event.logEventID, event.eventTimestamp, event.userID, event.source, 
       event.additionalDetails, event.insertByUserID, event.insertDateTime, 
       event.modifyByUserID, event.modifyDateTime 
  FROM event 
 WHERE event.orgID = 100 
   AND event.eventTimestamp >= 1535046151000 
ORDER BY event.eventID ASC limit 10001;

上面的查询需要 14 秒才能执行。

如果我删除 ORDER BY event.eventID ASC,则需要 0.01 秒

当前索引位于主列 idx1(eventID)。我们添加了第二个索引 idx2(orgID,eventTimestamp),但仍然没有看到性能提升。

除非用“USE Hint”指定,否则查询不使用新索引。使用提示并提供 idx2 需要 7 秒。

我们在 mysql 版本 5.6

关于提高执行时间的任何想法?

标签: mysqlperformancequery-performancemysql-5.6

解决方案


最糟糕的是Using filesort操作,我们应该看看我们是否可以按“索引顺序”返回行以避免该操作。

我很想添加一个索引:

... ON `event` (`orgid`,`eventid`,`eventtimestamp`)

我还会尝试调整查询。虽然不是绝对必要的,但我们可以orgid在子句中包含该列ORDER BY,因为子句中的条件WHERE保证我们只有一个值。

 ORDER BY event.orgid ASC, event.eventid ASC

这里的目的是为优化器提供尽可能多的信息,即有一个合适的索引来满足该ORDER BY子句。

用于EXPLAIN查看执行计划。

我们正在尝试让 MySQL 使用索引范围扫描orgid来以“索引”顺序返回行eventid。然后丢弃不满足条件的行eventtimestamp

SELECT event.eventid
     , event.orgid
     , event.objecttype
     , event.action
     , event.objectid
     , event.logeventid
     , event.eventtimestamp
     , event.userid
     , event.source
     , event.additionaldetails
     , event.insertbyuserid
     , event.insertdatetime
     , event.modifybyuserid
     , event.modifydatetime
  FROM event
 WHERE event.orgid = 100
   AND event.eventtimestamp >= 1535046151000
 ORDER
    BY event.orgid ASC 
     , event.eventid ASC
 LIMIT 10001

如果这不足以避免“使用文件排序”操作,那么我们可以尝试将条件eventtimestampWHERE子句移到HAVING子句中。(用 . 替换AND关键字HAVING。)


省略 的索引eventtimestamp可能足以获得合理的执行计划。

代替

... ON `event` (`orgid`,`eventid`,`eventtimestamp`)

这可能同样有效

... ON `event` (`orgid`,`eventid`)

推荐阅读