2017-01-18 1 views
0

いくつかのUNIONを含む長いMySQLクエリを実行する必要があります。サブクエリによっては実行に時間がかかるものがあります。私はテーブルのインデックスを作成しましたが、実行には約15秒かかります。私は実行時間を1秒に減らす必要があります。UNIONを使ってMySQLクエリを最適化する

ここ

はクエリです:

SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, NULL AS Ink_Type, NULL AS Industry, 
NULL AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, NULL AS Material, NULL AS Pattern, NULL AS Country_Origin, NULL AS Ships_From, pi.prd_img_name 
FROM products p 
LEFT JOIN product_image_p pi ON p.prd_id = pi.prd_id 
WHERE p.is_deleted = 'no' 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
NULL AS Ink_Type, NULL AS Industry, NULL AS Size, GROUP_CONCAT(decoration.dm_name SEPARATOR ', ') AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, NULL AS Material, 
NULL AS Pattern, NULL AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_dm pdm ON pdm.prd_id = p.prd_id 
JOIN decoration_method decoration ON decoration.dm_id = pdm.dm_id 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 

SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
NULL AS Ink_Type, NULL AS Industry, NULL AS Size, NULL AS Decoration_Method, GROUP_CONCAT(rush.rush_title SEPARATOR ', ') AS Rush_Production, NULL AS Themes, NULL AS Material, 
NULL AS Pattern, NULL AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_rush_title prt ON prt.prd_id = p.prd_id 
JOIN rush_title rush ON rush.rush_id = prt.rush_id 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, GROUP_CONCAT(ao.option_name SEPARATOR ', ') AS Item_Color, 
NULL AS Ink_Type, NULL AS Industry, NULL AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, NULL AS Material, NULL AS Pattern, 
NULL AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_attributes pa ON pa.prd_id = p.prd_id 
JOIN attributes_options ao ON ao.attr_opt_id = pa.attr_opt_id AND ao.attr_id = 19 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
GROUP_CONCAT(ao.option_name SEPARATOR ', ') AS Ink_Type, NULL AS Industry, NULL AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, NULL AS Material, 
NULL AS Pattern, NULL AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_attributes pa ON pa.prd_id = p.prd_id 
JOIN attributes_options ao ON ao.attr_opt_id = pa.attr_opt_id AND ao.attr_id = 10 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
NULL AS Ink_Type, GROUP_CONCAT(ao.option_name SEPARATOR ', ') AS Industry, NULL AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, NULL AS Material, 
NULL AS Pattern, NULL AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_attributes pa ON pa.prd_id = p.prd_id 
JOIN attributes_options ao ON ao.attr_opt_id = pa.attr_opt_id AND ao.attr_id = 18 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
NULL AS Ink_Type, NULL AS Industry, GROUP_CONCAT(ao.option_name SEPARATOR ', ') AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, NULL AS Material, 
NULL AS Pattern, NULL AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_attributes pa ON pa.prd_id = p.prd_id 
JOIN attributes_options ao ON ao.attr_opt_id = pa.attr_opt_id AND ao.attr_id IN (1, 13, 14) 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
NULL AS Ink_Type, NULL AS Industry, NULL AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, GROUP_CONCAT(ao.option_name) AS Themes, 
NULL AS Material, NULL AS Pattern, NULL AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_attributes pa ON pa.prd_id = p.prd_id 
JOIN attributes_options ao ON ao.attr_opt_id = pa.attr_opt_id AND ao.attr_id = 17 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
NULL AS Ink_Type, NULL AS Industry, NULL AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, GROUP_CONCAT(ao.option_name) AS Material, 
NULL AS Pattern, NULL AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_attributes pa ON pa.prd_id = p.prd_id 
JOIN attributes_options ao ON ao.attr_opt_id = pa.attr_opt_id AND ao.attr_id = 12 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
NULL AS Ink_Type, NULL AS Industry, NULL AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, NULL AS Material, 
GROUP_CONCAT(ao.option_name) AS Pattern, NULL AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_attributes pa ON pa.prd_id = p.prd_id 
JOIN attributes_options ao ON ao.attr_opt_id = pa.attr_opt_id AND ao.attr_id = 2 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
NULL AS Ink_Type, NULL AS Industry, NULL AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, NULL AS Material, 
NULL AS Pattern, GROUP_CONCAT(ao.option_name) AS Country_Origin, NULL AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_attributes pa ON pa.prd_id = p.prd_id 
JOIN attributes_options ao ON ao.attr_opt_id = pa.attr_opt_id AND ao.attr_id = 11 
WHERE p.is_deleted = 'no' 
group by prd_id 

UNION 
SELECT p.prd_id, NULL AS manu_name, NULL AS brand_name, NULL AS Categories, NULL AS Item_Color, 
NULL AS Ink_Type, NULL AS Industry, NULL AS Size, NULL AS Decoration_Method, NULL AS Rush_Production, NULL AS Themes, NULL AS Material, 
NULL AS Pattern, NULL AS Country_Origin, GROUP_CONCAT(ao.option_name) AS Ships_From, NULL AS prd_img_name 
FROM products p 
JOIN product_attributes pa ON pa.prd_id = p.prd_id 
JOIN attributes_options ao ON ao.attr_opt_id = pa.attr_opt_id AND ao.attr_id = 8 
WHERE p.is_deleted = 'no' 
group by prd_id 
+0

あなたが遅いこれらのどれをチェックしましたか? – xzoert

+1

質問の説明を表示してください –

+0

ao.attr_id = 19のものは非常に遅く、1秒以上かかります。 – Mainuddin

答えて

3

あなたが発生している問題が繰り返される製品の属性や製品オプションに加入し、完全なクエリを実行し、あなたが探しているコンポーネントごとに返された一つのレコードを取得しています。また、オプション表から出てくるすべてのパーツで、各製品ごとに1回事前に照会し、各コンポーネントを問題のPRD_IDの1レコードとして戻すことができます。私は強く(すでにそこにいない場合)を示唆している、そのコンポーネントの最適化を支援するため、

次のインデックス...

Table     Index 
product_attributes (prd_id, attr_opt_id) 
attributes_options (attr_opt_id, attr_id, option_name) 
products    (is_deleted, prd_id) 
product_dm   (prd_id, dm_id) 
decoration_method  (dm_id, dm_name) 
product_rush_title (prd_id, rush_id) 
rush_title   (rush_id, rush_title) 

システムが戻って行く必要はありませんので、インデックスは、インデックスを「カバー」されます生データページ装飾やラッシュコンテンツは他のテーブルから来ているためのような...

何かを内部の事前クエリとして部品のそれぞれを取得するには、次に

そのほとんどの結果を準備します、あまりにも彼らはprequeriedと要約することができますそして、あなたがあなたの主なクエリにサブクエリとしてそのクエリ全体をロールが、簡略化され、別名参照と各前グループ、連結フィールドの結果

を使用することができるだけで、製品IDに基づいて、その後左に参加している

SELECT 
     p2.prd_id, 
     GROUP_CONCAT(case when ao.attr_id = 19 
         then ao.option_name else null end SEPARATOR ', ') 
      AS Item_Color, 
     GROUP_CONCAT(case when ao.attr_id = 10 
         then ao.option_name else null end SEPARATOR ', ') 
      AS Ink_Type, 
     GROUP_CONCAT(case when ao.attr_id = 18 
         then ao.option_name else null end SEPARATOR ', ') 
      AS Industry, 
     GROUP_CONCAT(case when ao.attr_id = 17 
         then ao.option_name else null end SEPARATOR ', ') 
      AS Themes, 
     GROUP_CONCAT(case when ao.attr_id = 12 
         then ao.option_name else null end SEPARATOR ', ') 
      AS Material, 
     GROUP_CONCAT(case when ao.attr_id = 2 
         then ao.option_name else null end SEPARATOR ', ') 
      AS Pattern, 
     GROUP_CONCAT(case when ao.attr_id = 11 
         then ao.option_name else null end SEPARATOR ', ') 
      AS Country_Origin, 
     GROUP_CONCAT(case when ao.attr_id = 8 
         then ao.option_name else null end SEPARATOR ', ') 
      AS Ships_From, 
     GROUP_CONCAT(case when ao.attr_id IN (1, 13, 14) 
         then ao.option_name else null end SEPARATOR ', ') 
      AS Size 
    from 
     products p2 
     JOIN product_attributes pa 
      ON p2.prd_id = pa.prd_id 
      JOIN attributes_options ao 
       ON pa.attr_opt_id = ao.attr_opt_id     
    WHERE 
     p2.is_deleted = 'no' 
    group by 
     p2.prd_id 

化さ

SELECT 
     p.prd_id, 
     NULL AS manu_name, 
     NULL AS brand_name, 
     NULL AS Categories, 
     preQuery.Item_Color, 
     preQuery.Ink_Type, 
     preQuery.Industry, 
     preQuery.Themes, 
     preQuery.Material, 
     preQuery.Pattern, 
     preQuery.Country_Origin, 
     preQuery.Ships_From, 
     preQuery.Size, 
     tmpDeco.Decoration_Method, 
     tmpRush.Rush_Production, 
     pi.prd_img_name 
    FROM 
     products p 
     LEFT JOIN product_image_p pi 
      ON p.prd_id = pi.prd_id 

     LEFT JOIN 
     (THE PRE-QUERY SAMPLE ABOVE) PreQuery 
      ON p.prd_id = PreQuery.prd_id 

     LEFT JOIN 
     (select 
       p2.prd_id, 
       GROUP_CONCAT(decoration.dm_name SEPARATOR ', ') AS Decoration_Method 
       FROM 
       products p2 
        JOIN product_dm pdm 
         ON p2.prd_id = pdm.prd_id 
         JOIN decoration_method decoration ; 
          ON decoration.dm_id = pdm.dm_id 
       WHERE 
       p2.is_deleted = 'no' 
       group by 
       p2.prd_id) as tmpDeco 
      ON p.prd_id = tmpDeco.prd_id 

     LEFT JOIN 
     (select 
       p2.prd_id, 
       GROUP_CONCAT(rush.rush_title SEPARATOR ', ') AS Rush_Production 
       FROM 
       products p2 
        JOIN product_rush_title prt 
         ON p2.prd_id = prt.prd_id 
         JOIN rush_title rush 
          ON prt.rush_id = rush.rush_id 
       WHERE 
       p2.is_deleted = 'no' 
       group by 
       p2.prd_id) as tmpRush 
      ON p.prd_id = tmpRush.prd_id 

    WHERE 
     p.is_deleted = 'no' 

同じテーブルを起源とするすべての共通の説明要素を一度に取得し、単一のエイリアス参照に基づいて終了すると簡単に結合することができればうれしいことです。

私はタイプ-oまたは2を持っているかもしれませんが、必要に応じてそれ以外の場合は正しいと思います。あなたはまた、Manu_Name、Brand_Name、Categoryについて何も持っていなかったので、そのコンポーネントを完成させる必要があります。

フォローアップ...あなたの最新に基づいて

、私は何だろうと、各フィールドを保持するために、製品テーブルにいくつかのフィールドを追加しています。次に、製品に追加するときに製品属性テーブルへの挿入/更新/削除のトリガーを作成します。インパクトが発生した場合は、問題のフィールドで単純なsql-select group_concat()を実行し、主製品テーブルを直ちに更新します。はい、これはある範囲に非正規化されますが、集中的なクエリを実行してパフォーマンスを低下させる必要は完全に簡素化されます。

私の答えin this other stack questionを見てください。私はそのような同様のトリガーを作成しています。このように、プライマリテーブルは事前に集約されていますので、1つの製品で1つのフィールドしか実行できないため、トリガはほぼ即座に動作します。

+0

この素晴らしい努力に感謝します。あなたの提案されたクエリは目立った改善をしませんでした。私のクエリは5.7秒かかり、4.7秒かかります。 ボトルネックの原因となるものがあると思います。 – Mainuddin

+0

@Mainuddin、TRIGGERsを実装している別のスタックポストへのリダイレクトと明確化のための改訂された答え。 – DRapp

+0

私はついに、検索に関連するデータだけを含む専用の検索用テーブルを作成することにしました。トリガは、製品や他のテーブルに変更が加えられたときに更新されます。それは期待通りに超高速になります。 もう一度@DRappに感謝します。 – Mainuddin

0

パフォーマンス上の問題の一部は、「過剰正規化」によるものです。どのようにGROUP_CONCAT(ao.option_name)が属性表から来るのではなく、別のJOINを経由していることに注目してください。 aoを取り除き、option_namesproduct_attributesに移動することをお勧めします。

(これは、クエリ内の病気の数をカバーするために、表面には、思わDRappの答え​​、@に加えている。)