我有一个相对简单的游戏。我需要帮助我认为这个查询没有正确优化。
我有一个标准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
我有以下索引:
用户 id - primary, username - unique
扩展 id - primary, order_hint - index
playlog expansions_id - foreign, user_id - foreign
我拿了一个数据库类一段时间了,我记得使用临时和filesorts应该是坏的但我真的不记得如何纠正它或者如果它在这个例子中没问题(如果我不选择用户名,它在Explain的第一行中也说“使用索引”)
答案 0 :(得分: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告诉引擎按照我说过的顺序查询,不要让它解释可能效率较低的查询路径。