2013-09-29 31 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告诉引擎按照我所说的顺序进行查询,而不是让它解释可能效率较低的查询路径。