2017-01-11 12 views
0

私は3つのテーブルmessages,message_recipientsおよびusersでクエリを実行しています。 messagesテーブルのSQLクエリのパフォーマンスを向上させる

表構造:このテーブルの

id int pk 
message_id int 
message text 
user_id int 
... 

指数はuser_idmessage_ididです。 message_recipientsテーブルの

表構造:

id int pk 
message_id int 
read_date datetime 
user_id int 
... 

インデックスidmessage_iduser_idです。 usersテーブルの

表構造:

id int pk 
display_name varchar 
... 

指数はidです。

私は、これらのテーブルに対して、次のクエリ実行しています:

SELECT 
    m.*, 
    if(m.user_id = 0, 'Campus Manager', u.display_name) AS name, 
    mr.read_date, 
    IF(m1.message_id > 0 and m1.user_id=1, true, false) as replied 
FROM 
    messages m 
JOIN 
    message_recipients mr 
ON 
    mr.message_id = m.id 
LEFT JOIN 
    users u 
ON 
    u.UID = m.user_id 
LEFT JOIN 
    messages m1 
ON 
    m1.message_id = m.id 
WHERE 
    mr.user_id = 1 
AND 
    m.published = 1 
GROUP BY 
    mr.message_id 
ORDER BY 
    m.created DESC 

EXPLAINをこのクエリに対して次のデータを返します:@ e4c5によって示唆されるように Explain query result

UPDATE 、私は新しい複合を追加しました(公開された、user_id、作成された)インデックスであり、今、説明クエリはこれを示します: Updated explain query

多くの時間がかかるので、必要なインデックス(あれば)を追加してこのクエリを最適化するにはどうすればよいですか?

答えて

0

クエリ時間を3秒から0に短縮できました。新しいインデックスをmessagesテーブルとmessage_recipientsテーブルに追加し、messagesテーブルのデータベースエンジンをMyISAMからInnoDBに変更することで、1秒です。 message_id_2message_recipientsテーブル上の2つの列に加えpublished, user_id, created

複合インデックス - -

指数compositemessagesテーブルにそれぞれの順序でこれらのカラムに加え今示すクエリをEXPLAIN message_id, user_id

EXPLAIN Query

0
  • GROUP BYは、集約されていないすべての列をリストする必要があります。私はそれが混乱すると思う。なぜGROUP BYが必要なのですか?
  • なぜmessages.idをmessages_idにリンクしていますか?これは階層的な表ですが、列名は 'parent_id'と似ていませんか?
  • "インデックスはid、message_idおよびuser_idにあります" - それは複合インデックスか3つの単一列インデックスですか? (大きな違いがあります)あいまいな言い換えの代わりにSHOW CREATE TABLEを表示する方が良いでしょう。
  • user_id = 1が多かったですか?つまり、何千もの行が予想されますか?この質問は彼にとってただの問題ですか?
  • LEFT JOINを使用すると、m1.message_idNULLになる可能性がありますが、その参照はその可能性を無視しているようです。
  • これはスレッドに関する主要情報と個々の応答の両方を含むメッセージスレッドを含む単一のテーブルであれば、それは悪い設計であることを示唆しています。 (私は一度だけこのミスを犯しました)スレッドごとに1つの行とコメントごとに1つの行を持つテーブルを持つ方が良いと思います。 1スレッド:多くのコメント。したがって、コメントテーブルにはthread_idがあります。
+0

グループ化が必要です重複を避けるために。それは返されたメッセージの 'id'が' message_id'に行く階層的なテーブルです。いいえ、3つの個別のインデックスがあります。いいえ、問題は単一の問題だけでなくすべてのユーザーにあります。はい、 'm1.message_id'は' null'でもかまいません。これは、メッセージがまだ返信されていないことを意味します。メッセージスレッドのようなものはなく、特定のメッセージへの返信として送られたメッセージの 'id'だけです。 – Ehs4n

関連する問題