-4

我有一个相对简单的游戏。我需要帮助我认为此查询未正确优化。

我有一张标准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

播放日志 expansions_id - foreign, user_id - foreign

不久前我上了一个数据库类,我记得使用临时和文件排序应该是坏的,但我真的不记得如何纠正它或者在这种情况下是否可以(另外,如果我不选择用户名,它在解释的第一行也说“使用索引”)

4

1 回答 1

0

您的查询看起来大部分是准确的,但评论的痕迹是负面的。我重写了查询以更明确地显示表和连接条件的关系。你有左与内连接。从您的描述中可以看出,“扩展”表就像游戏中可用的扩展的主列表(如查找表)。记录进入 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 告诉引擎按照我所说的顺序进行查询,而不是让它解释可能效率较低的查询路径。

于 2013-09-30T02:25:13.200 回答