2016-08-24 6 views
0

私は、ほぼ4000レコードのリレーショナルMySQLデータベースを持っています。連絡先テーブルは、多人数対多の関係を持つキーワードテーブルとメモテーブルの両方に関連しています。私は、各連絡先レコードと、各連絡先に対して、グループconcat関数内のすべての関連するメモとキーワードを取得するクエリ(PHPを使用)を書いています。連絡先だけを取得すると、クエリは比較的速く実行されますが、2つの左の結合とグループの連結では、ほぼ30秒かかります。これをスピードアップする方法はありますか?パフォーマンスに影響を与える複数の結合によるSQLクエリ

SELECT c.*, GROUP_CONCAT(DISTINCT n.id, '[-]', n.value, '' SEPARATOR '---') as notes, 
     GROUP_CONCAT(DISTINCT kk.id, '[-]', kk.value) as keywords 
    FROM contacts c 
    LEFT JOIN notes n ON c.id LIKE n._contactID 
    LEFT JOIN 
     (SELECT k.*, kc._contactID as contactID 
      FROM keywords k 
      INNER JOIN keywords_contacts kc ON k.id LIKE kc._keywordID 
     ) kk ON kk.contactID LIKE c.id 
    GROUP BY c.id 
    ORDER BY c.`Last Name`, c.`First Name` 
+0

データベースにインデックスを設定しましたか?インデックスがクエリを高速化する可能性があります。 –

+0

私の考え方によれば、SQLでは、GROUP_CONCATが回答の一部を形成する必要はありません。特に、アプリケーションレベルのコードで作業する場合は問題ありません。スピードの鍵はインデックスにありますが、私たちがそれに着手する前に、適切なCREATEとINSERTステートメントを希望の結果と一緒に提供することを検討してください。 – Strawberry

+0

@Strawberry Hareshのソリューションを使用して問題を解決している間、私はあなたのコメントを理解したい。分析して遊ぶことができるコードサンプルを提供できると思いますか? –

答えて

1

Iクエリ私はここに性能もが低いので、=演算子を使用して、外部キーフィールド_contactIDにインデックスを与える行っているなどの、c.id LIKE n._contactIDを見ることができます:

は、ここに私のクエリです。

k.id LIKE kc._keywordIDと同じ= LIKEの代わりに=演算子を使用し、フィールド_keywordIDにインデックスを適用します。

+0

ああ、ありがとう、これはトリックでした!私は先週デバッグしていて忘れてしまったときに '='から 'Like'に変更しました。 –

+0

私のトリックについて聞いてくれてありがとうございます。投票を諦めることも忘れないでください。 –

0

はい、LIKEの代わりに=を使用してください。ワイルドカードが必要な場合は、first_name LIKE 'H%'などの場合はLIKEにしてください。

=に変更すると、依然として低速のクエリが見つかることがあります。

LEFTが必要ない場合は、使用しないでください。通常、サブクエリ( 'LEFT JOIN (SELECT ...)'を参照)である 'table'で始めるのが速くなりますが、LEFTを使用するとそのようなことが起こりにくくなります。

GROUP BY c.`Last Name`, c.`First Name`, c.id 
ORDER BY c.`Last Name`, c.`First Name`, c.id 

SHOW CREATE TABLEEXPLAIN SELECT ...を提供してください、私たちはインデックスを批評することができます:GROUP BYORDER BYが同じである

場合は、ソート一時テーブルとを回避することができます。

関連する問題