2013-09-29 33 views
-4

我有一個相對簡單的遊戲。我需要幫助,我認爲這個查詢沒有正確優化。需要幫助優化查詢,EXPLAIN說「使用臨時的,使用filesort」

我有一個標準的users表。有一個expansions表,其中包含有關遊戲中擴展的一般信息。每次用戶在擴展中擊敗一個級別時,會將一行添加到playlog,表示他們的最終得分(因此首先,他們的擴展名在播放列表中有0行)。

EXPLAIN SELECT users.username, expansions.title, expansions.description, 
COUNT(playlog.id) as levels_beaten 
FROM users 
INNER JOIN expansions 
LEFT JOIN playlog ON users.id = playlog.user_id 
AND expansions.id = playlog.expansions_id 
WHERE users.id = 10 
GROUP BY expansions.id 
ORDER BY expansions.order_hint DESC 

explained query

example select

我有以下指標:

用戶id - primary, username - unique

擴展id - primary, order_hint - index

playlogexpansions_id - foreign, user_id - foreign

我參加了一個數據庫類一段時間回來,我記得使用臨時和filesorts被認爲是不好的,但我真的不記得如何糾正它,或者如果它在這種情況下也沒關係(如果我不選擇用戶名,它也會在Explain的第一行中顯示「Using Index」)

+3

'INNER JOIN expansions' join _on what_? – wildplasser

+0

@wildplasser:我爲此添加了一個ON,但我認爲它讓情況變得更糟:http://i.imgur.com/eNobnhd.jpg – y2k

+0

我沒有看到它。請發佈** real **代碼。 downvoting ... – wildplasser

回答

0

您的查詢看起來大部分是準確的,但評論的蹤跡是負面的旋轉。我重寫了查詢以更明確地顯示錶和聯接條件的關係。你已經離開了vs內部聯接。從您的描述中可以看出,「Expansions」表格就像遊戲中可用的擴展主表(如查找表)。記錄進入PLAYLOG的唯一方式是如果有人完成了給定的擴展。也就是說,從用戶開始他們的播放歷史記錄。如果沒有記錄,無論如何你都完成了。如果有一個playlog,然後加入到擴展來獲取描述。如果沒有人完成任何這樣的級別,則無需獲得擴展描述。

SELECT 
     users.username, 
     expansions.title, 
     expansions.description, 
     COUNT(*) as levels_beaten 
    FROM 
     users 
     JOIN playlog 
      ON users.id = playlog.user_id 
      JOIN expansions 
       ON playlog.expansions_id = expansions.id 
    WHERE 
     users.id = 10 
    GROUP BY 
     expansions.id 
    ORDER BY 
     expansions.order_hint DESC 

如果查詢仍然出現引起的問題,然後,我會建議增加關鍵字「STRAIGHT_JOIN」如

SELECT STRAIGHT_JOIN ...查詢的其餘部分。

STRAIGHT_JOIN告訴引擎按照我所說的順序進行查詢,而不是讓它解釋可能效率較低的查詢路徑。