2012-04-03 76 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)必須刪除文件排序。

相關問題