2017-05-17 4 views
1

ルックアップテーブルに参加する3つの異なるテーブルからデータを取得するクエリを作成しようとしています。私の問題は、クエリの実行に時間がかかるということであるパフォーマンスの問題を特定する方法 - MYSQL

(1時間を取って、私は何かがPythonスクリプトは、クエリを実行し、ファイルに結果を書いている、間違っていたと仮定すると待ってあきらめました)

クエリは次のようになります。

SELECT a.id, 
GROUP_CONCAT(DISTINCT b.product_id SEPARATOR ':') AS b_pids, 
GROUP_CONCAT(DISTINCT c.product_id SEPARATOR ':') AS c_pids, 
GROUP_CONCAT(DISTINCT d.product_id SEPARATOR ':') AS d_ids 
FROM a_table a 
LEFT JOIN b_table b ON a.customer_account_guid = b.customer_account_guid 
LEFT JOIN c_table c ON b.customer_account_guid = c.customer_account_guid 
LEFT JOIN d_table d ON c.customer_account_guid = d.customer_account_guid 
WHERE a.category = 'product_category' AND a.location = 'UK' GROUP BY a.id 

このクエリの説明結果は次のとおりです。

id | select_type | table | type  | possible_keys                   | key      | key_len | ref      | rows |filtered |Extra 
1 | SIMPLE  | a  | ref  | PRIMARY,idx_id,idx_customer_account_guid,idx_category_location,idx_category,idx_location | idx_category_location  | 47  | const,const    | 1211986 |100  |Using index condition 
1 | SIMPLE  | b  | ref  | idx_customer_account_guid                | idx_customer_account_guid | 300  | a.customer_account_guid | 6  |100  |NULL 
1 | SIMPLE  | c  | ref  | idx_customer_account_guid                | idx_customer_account_guid | 300  | b.customer_account_guid | 18  |100  |NULL 
1 | SIMPLE  | d  | ref  | idx_customer_account_guid                | idx_customer_account_guid | 300  | c.customer_account_guid | 2  |100  |NULL 

テーブルのレコード(カウント)です。

a_table - 3 million

b_table - 8 million

c_table - 2 million

d_table - 4 million

あなたはインデックスが大丈夫であるように見えるとクエリは、任意のアイデアスーパー複雑ではありません見ることができるようになぜ1時間以上かかるのですか?私はそれが上記のカウントでそれほど長くはならないと思っていますか、間違っていますか?

+1

実際に結果にいくつの行がありますか?また、300はGUIDの長さが少し高いようです。インデックスの長さ(またはフィールドの長さ)を実際の最大GUIDの長さに減らすと役立ちます。 – Vatev

+0

は約1millionの結果になるはずです...提案のおかげで、インデックスlenを減らし、役立つかどうかを確認します。 – Bodao

+1

あなたはSQLクエリ***を実行するのに要した時間と、pythonがファイル*に結果を書き込むのにかかる時間を区別することができます。乾杯 – Martin

答えて

2

あなたはジョインを使ってばかげた数の行を生成しています。代わりに、集計前には参加:

SELECT a.id, b.b_pids, c.c_pids, d.d_ids 
FROM a_table a LEFT JOIN 
    (SELECT b.customer_account_guid, GROUP_CONCAT(b.product_id SEPARATOR ':') as b_pids 
     FROM b_table b 
     GROUP BY b.customer_account_guid 
    ) b 
    ON a.customer_account_guid = b.customer_account_guid LEFT JOIN 
    (SELECT c.customer_account_guid, GROUP_CONCAT(c.product_id SEPARATOR ':') as c_pids 
     FROM c_table c 
     GROUP BY b.customer_account_guid 
    ) c 
    ON a.customer_account_guid = c.customer_account_guid LEFT JOIN 
    (SELECT d.customer_account_guid, GROUP_CONCAT(d.product_id SEPARATOR ':') as d_pids 
     FROM d_table d 
     GROUP BY d.customer_account_guid 
    ) d 
    ON a.customer_account_guid = d.customer_account_guid 
WHERE a.category = 'product_category' AND a.location = 'UK'; 

私はGROUP_CONCAT()からDISTINCTを削除しました。あなたはまだそれが必要かもしれません。

EDIT:外部クエリでのフィルタリングを考える

、相関サブクエリが最善のアプローチであるかもしれない:このバージョンのために

SELECT a.id, 
     (SELECT GROUP_CONCAT(b.product_id SEPARATOR ':') as b_pids 
     FROM b_table b 
     WHERE a.customer_account_guid = b.customer_account_guid 
     ) b_pids, 
     (SELECT GROUP_CONCAT(c.product_id SEPARATOR ':') as b_pids 
     FROM c_table c 
     WHERE a.customer_account_guid = c.customer_account_guid 
     ) b_pids, 
     (SELECT GROUP_CONCAT(d.product_id SEPARATOR ':') 
     FROM d_table d 
     WHERE a.customer_account_guid = d.customer_account_guid 
     ) d_pids 
FROM a_table a LEFT JOIN 
WHERE a.category = 'product_category' AND a.location = 'UK'; 

、あなたはa_table(category, location, customer_account_guid)上や他のテーブルのそれぞれのインデックスをしたいです、 (customer_account_guid, product_id)

+0

あなたの提案に感謝して、説明の結果に基づいてより複雑に思えましたが、私は試しました。そして、それを実行すると、限界100で、実行には15分かかります...理由はわかりません – Bodao

+0

私はあなたの編集ソリューションの方向に向かっていましたが、それを行う最良の方法はわかりませんでした...編集提案トリック、それは10未満で走った! ty so much – Bodao

+0

私はこの解決策がなぜ左の結合を実行するのか不思議です、余裕があれば分かりますか? – Bodao

関連する問題