2012-04-03 66 views
5

我正在使用一个简单的MySQL查询,但由于使用ORDER BY,性能实际上很糟糕。我无法弄清楚为什么MySQL使用filesort和临时。使用filesort和临时的MySQL查询

我的查询是:

EXPLAIN 
SELECT * FROM Events 
INNER JOIN EventLogFiles ON ServerID = 42 
AND Events.LogFileID = EventLogFiles.LogFileID 
ORDER BY ReportID DESC , TimeWritten DESC 
LIMIT 100 

这是EXPLAIN输出:

Mysql EXPLAIN output

表活动结构

Table Events structure

表活动指数

Table Events indexes

表EventLogFiles结构

Table EventLogFiles structure

表EventLogFiles指标

Table EventLogFiles indexes

UPDATE:

我试图创建两个新索引,但两者仍然强制MySQL使用filesort和临时的。

ALTER TABLE Events ADD INDEX `ReportID_TimeWritten_ServerID_LogFileID` (ReportID DESC, TimeWritten DESC, ServerID, LogFileID) 

ALTER TABLE Events ADD INDEX `ServerID_LogFileID_ReportID_TimeWritten` (ServerID, LogFileID, ReportID DESC, TimeWritten DESC) 
+1

您可以在不订购的情况下将前100个记录输出到临时表,然后仅使用另一个查询来排序这100个记录? – 2012-04-03 19:07:32

+1

将Events.LogFileID添加到多列索引。 – 2012-04-03 19:17:21

+0

你可以尝试创建索引'ServerID_ReportID_TimeWritten_LogFileID','ReportID_TimeWritten_ServerID_LogFileID'?我认为其中之一会有所帮助。 – 2012-04-03 19:18:02

回答

4

为了利用指数都选择和排序,你需要有所有对事件进行了多列索引以下列:(ServerID, LogFileID, ReportID, TimeWritten)

目前,MySQL不能利用现有的多列索引,因为它不包含LogFileID,它在ON子句中。

如果您在MySQL中首先从事件日志文件中选择时遇到问题,您可以将INNER JOIN更改为STRAIGHT JOIN,以确保MySQL始终首先使用您的索引从事件中选择事件。

+0

Marcus,我遵循你的建议,但仍然是同样的问题,你有什么想法吗? 注意:ServerID_LogFileID_ReportID_TimeWritten | key_len:4 |额外:使用临时;对于多列索引,使用filesort – koen 2012-04-03 20:20:34

+0

Key_len不能为4。它应该是16.我会仔细检查您的查询和索引。 – 2012-04-04 19:16:24

0

为了获得,没有临时表和文件类型的工作,你必须创建一个索引(ServerID, LogFileID, ReportID)TimeWritten必须是连续的一样,你一直使用ReportIDauto_increment,所以使得ORDER BY ReportID(PK - Order Physical)必须删除文件排序。

相关问题