-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

しばらく前にデータベースクラスを受講しましたが、一時的なファイルソートの使用が悪いと思われていたことを覚えていますが、それを修正する方法や、このインスタンスで問題ないかどうかはよく覚えていません (また、ユーザー名を選択しない場合、それはExplain の最初の行にも「Using Index」と記載されています)。

4

1 に答える 1

0

あなたのクエリはおおむね正確に見えましたが、コメントの跡はマイナスに転じていました。テーブルと結合条件の関係をより明確に示すために、クエリを書き直しました。左結合と内部結合がありました。あなたの説明から、「Expansions」テーブルは、ゲームで利用可能な拡張のマスターリストのようなものです (ルックアップテーブルのような)。レコードが 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 に答える