我们有一个事件服务,它返回按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”指定,否则查询不会使用新索引。使用use提示并提供idx2需要7秒钟。
我们使用的是MySQL5.6版本
有没有关于提高执行时间的想法?
3条答案
按热度按时间daupos2t1#
没有必要两者都用
WHERE
以及HAVING
. 只是使用WHERE orgID = 100 AND eventTimestamp >= somevalue
.SELECT lots of stuff ORDER BY something LIMIT count
是一个臭名昭著的性能反模式。为什么?它把一堆乱七八糟的行排序,只是为了丢弃其中的大部分。您可以使用延迟连接来改善这一点。在子查询中获取所需行的pk值,然后检索详细信息。
对子查询尝试这样的操作。
您可能可以使用上的复合索引来加速此查询
(orgID, eventTimestamp)
. (如果表使用myisam,那么在索引中包含pk,如下所示(orgID, eventTimestamp, eventID)
.然后执行此操作以从所需的行中获取数据详细信息。
这是因为它排序,然后丢弃主键值。那更便宜。
如果eventtimestamp和eventid值都严格按升序排列,那么还有另一种优化方法。也就是说,如果插入的每一行都有当前时间戳,则可以利用这一事实。
在上使用索引
orgID
另一个在eventTimestamp
对于这种查询。它之所以有效,是因为时间戳大于开始时间戳的每一行都有一个eventid>=第一行中与时间标准匹配的eventid。希望您的eventtimestamp列
BIGINT
或者DOUBLE
数据类型。javascript时间戳(unix纪元后的毫秒数)不适合32位整数。如果索引正确,较大的数据类型不会对性能造成太大的差异。t1rydlwq2#
同时具备以下两个条件:
优化器可以使用它们中的任何一个,并且可以根据统计信息选择更好的一个。向任一列添加额外列都不会加快此查询的速度。第二个索引将避免文件排序,但可能不会更快。
如果输出是一个网页,我建议
LIMIT 10001
很难操作。dgjrabp23#
最糟糕的是
Using filesort
操作时,我们应该看看是否可以获得按“索引顺序”返回的行,以避免该操作。我很想添加一个索引:
我还尝试调整查询。虽然不是严格必要的,但我们可以包括
orgid
中的列ORDER BY
条款,因为WHERE
条款向我们保证单一价值。这里的目的是给优化器尽可能多的信息,有一个合适的索引来满足
ORDER BY
条款。使用
EXPLAIN
看看执行计划。我们正在尝试让mysql使用索引范围扫描
orgid
按“索引”顺序返回行的步骤eventid
. 然后丢弃不满足条件的行eventtimestamp
.如果这还不足以避免“using filesort”操作,那么我们可以尝试在
eventtimestamp
在外面WHERE
从句成句HAVING
条款(更换AND
关键字HAVING
.)省略
eventtimestamp
可能足以得到一个合理的执行计划。而不是
这也许同样有效