2012-11-29 38 views
28

我正在使用一些查找表以及主日誌表的事件跟蹤系統。在我撰寫的報告中,可以選擇一個對象來查看統計信息。界面按重要性遞減的順序顯示所有對象(即命中)。使用索引,使用臨時的,使用filesort - 如何解決這個問題?

兩個表(略下調,但你的GIST)的模式:

CREATE TABLE IF NOT EXISTS `event_log` (
    `event_id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_id` int(5) DEFAULT NULL, 
    `object_id` int(5) DEFAULT NULL, 
    `event_date` datetime DEFAULT NULL, 
    PRIMARY KEY (`event_id`), 
    KEY `user_id` (`user_id`), 
    KEY `object_id` (`object_id`) 
); 

CREATE TABLE IF NOT EXISTS `lookup_event_objects` (
    `object_id` int(11) NOT NULL AUTO_INCREMENT, 
    `object_desc` varchar(255) NOT NULL, 
    PRIMARY KEY (`object_id`) 
); 

我遇到的麻煩查詢如下。它適用於大約100個條目的表格,但EXPLAIN有點讓我擔心。

explain SELECT 
      el.object_id, 
      leo.object_desc, 
      COUNT(el.object_id) as count_rows 
     FROM 
      event_log el 
      LEFT JOIN lookup_event_objects leo ON leo.object_id = el.object_id 
     GROUP BY 
      el.object_id 
     ORDER BY 
      count_rows DESC, 
      leo.object_desc ASC 

返回: Using index; Using temporary; Using filesort

那麼 - 有什麼錯我的架構和/或查詢爲MySQL依傍temporaryfilesort?或者它是否可以使用ORDER BY進行優化?

回答

63

好,the doc會給出確切的原因時,「使用臨時」將出現:

臨時表可以如這些條件下創建:

如果有一個ORDER BY子句和不同GROUP BY子句,或者如果ORDER BY或GROUP BY包含來自聯接隊列中第一個表以外的表的列,則創建一個臨時表。

DISTINCT與ORDER BY結合可能需要臨時表。

如果使用SQL_SMALL_RESULT選項,MySQL將使用內存中的 臨時表,除非查詢還包含需要磁盤存儲的元素(稍後描述的 )。

快速掃描顯示您患有#1。

this blog從2009年開始說「使用filesort」意味着該排序不能用索引執行。既然你是按計算機領域排序的,那也是一樣的。

所以,這就是「錯誤的」。

+0

我曾經從該查詢返回的最大對象數爲<300,雖然我將有可能擁有數百萬行的EVENT_LOG。我確認當我刪除ORDER BY時,使用臨時文件和使用filesort會消失。我會嘗試改變這一點,以便使用腳本語言(PHP)進行排序(在數組中)。感謝您的回覆和鏈接。 –

+1

在MySQL中進行排序仍然可能更有效 - 它已經將數據加載到數據結構中,等等。 –

+0

它肯定會更乾淨。感謝您的反饋。 –

1

以下是創建臨時表的條件。 UNION查詢使用臨時表。

某些視圖需要使用TEMPTABLE算法或使用UNION或聚合評估的臨時表。

如果存在ORDER BY子句和不同的GROUP BY子句,或者如果ORDER BY或GROUP BY包含除聯接隊列中第一個表以外的表的列,則會創建一個臨時表。

DISTINCT與ORDER BY結合可能需要臨時表。

如果使用SQL_SMALL_RESULT選項,MySQL將使用內存中的臨時表,除非查詢還包含需要磁盤存儲的元素(稍後介紹)。

按照由MySQL這個鏈接: http://dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html

1

更新爲MySQL 5.7(src):

服務器創建條件下,臨時表像這樣的:

  • 評價UNION聲明,稍後會有一些例外情況。

  • 評價的一些視圖,例如那些使用不是Temptable算法,UNION,或聚集。

  • 評價派生表的(在FROM子句子查詢)。爲子查詢或半聯接物化(參見8.2.2節,「優化子查詢,派生表和視圖引用」)創建

  • 表。包含ORDER BY子句和不同的GROUP BY子句語句

  • 評價,或者用於其中ORDER BY或GROUP BY包含比在加入隊列中的第一個表的其他表的列。

  • 評價DISTINCT結合ORDER BY可能需要臨時表。

  • 對於使用SQL_SMALL_RESULT修飾符的查詢,MySQL使用內存中的臨時表,除非查詢還包含需要磁盤存儲的元素(稍後介紹)。

  • 要評估從中選擇並插入同一個表的INSERT ... SELECT語句,MySQL會創建一個內部臨時表來存放SELECT中的行,然後將這些行插入到目標表中。請參見第13.2.5.1節「INSERT ... SELECT語法」。

  • 評價多表UPDATE語句。

  • GROUP_CONCAT的評價()或COUNT(DISTINCT)表達式。

相關問題