2016-12-15 15 views
1

私は、mySQLサーバー上で更新クエリ/サブクエリを実行しています。終了するのに12分かかります。十分に最適化されていないと思います。低速SQLクエリを最適化する方法が必要ですか?

誰かがそれを最適化するために考えてもらえますか?

ありがとうございます。

UPDATE `TABLE_1` C 
INNER JOIN(

    SELECT Cust_No, 

    #current year sales 

    (SELECT SUM(`Sales`) 
    FROM `TABLE_2` 
    WHERE Year = 2016 
     AND Cust_No = p.Cust_No 
    ) as CY_TOTAL_SALES, 

    # Get previou year sales 

     (SELECT SUM(`Sales`) 
    FROM `TABLE_2` 
    WHERE Year = 2015 
     AND Cust_No = p.Cust_No 
    ) as PY_TOTAL_SALES 

    FROM `TABLE_2` p 
    WHERE Year >= 2015 
     AND Year <= 2016 

) AS A ON C.`customer_number` = A.Cust_No 
    SET C.CY_TOTAL_SALES = A.CY_TOTAL_SALES, 
     C.PY_TOTAL_SALES = A.PY_TOTAL_SALES; 

TABLE_1はTABLE_2は何それがないことは、更新TABLE_1ある25万記録(CUST_NOは一意ではありませんが、構築されたインデックスを作成しました)

が含まれている28,000記録(CUSTOMER_NUMBERフィールドが固有で構築されたインデックスを作成しました)

が含まれていますTable_2を結合し、サブクエリを使用してTABLE_2の両方の年の合計売上値を合計し、TABLE_1 WHERE TABLE_1のカスタム番号がTABLE_2 Cust_noと一致するように値を更新します。

+2

クエリを「EXPLAIN」で実行し、出力を送信します。これは、クエリのどの部分が高価であるかを示します。 –

答えて

3

私は考えられる解決策のいくつかを考えることができます。

方法1

ちょうど1サブクエリを実行し、任意の相関副問合せを行い、その合計は条件付きで年に基づいていません。

UPDATE TABLE_1 C 
INNER JOIN (
    SELECT Cust_No, 
    SUM(IF(Year=2015, Sales, 0)) AS PY_TOTAL_SALES, 
    SUM(IF(Year=2016, Sales, 0)) AS CY_TOTAL_SALES 
    FROM TABLE_2 
    WHERE Year IN (2015, 2016) 
    GROUP BY Cust_No 
) AS S ON C.customer_number = S.Cust_No 
SET C.PY_TOTAL_SALES = S.PY_TOTAL_SALES, 
    C.CY_TOTAL_SALES = S.CY_TOTAL_SALES; 

方法2

全くサブクエリを行いません。

まず、すべての顧客のための総売上うちゼロ:

UPDATE TABLE_1 C 
SET C.CY_TOTAL_SALES = 0, 
    C.PY_TOTAL_SALES = 0; 

は次に任意のサブクエリまたはSUM()呼び出しを使用せずに参加し、顧客のための総売上高に一度、各販売図1を追加します。

UPDATE TABLE_1 AS C 
INNER JOIN TABLE_2 AS S ON C.customer_number = S.Cust_No 
SET C.CY_TOTAL_SALES = C.CY_TOTAL_SALES + IF(S.Year=2016, S.Sales, 0) 
    C.PY_TOTAL_SALES = C.PY_TOTAL_SALES + IF(S.Year=2015, S.Sales, 0) 
WHERE S.Year IN (2015, 2016); 

これらの両方のソリューションでは、列(Cust_No、Year、Sales)にTABLE_2のインデックスが必要です。


その間、元のクエリが非常に遅い理由を少し説明できます。サブクエリでは、250,000行(すべての行が2015〜2016年であると仮定します)というTABLE_2が読み込まれ、行ごとに対応する顧客の合計売上が計算されます。つまり、顧客ごとに同じ合計を何度も計算します。

相関サブクエリが500,000回実行されています。それは実際には奇跡です、それはわずか12分かかります。

このように、サブクエリが原因で、この結果全体が250,000行の一時テーブルに保存されます。

次に、一時表をTABLE_1に結合し、各顧客ごとにCY_TOTAL_SALESおよびPY_TOTAL_SALESを設定します。あなたはそれを知らないが、顧客ごとに同じ合計を何度も設定している。

+0

ありがとうございます。あなたのソリューションを試してみましょう。 –

+1

こんにちはビル、詳細な説明と1つの方法は最高1.2秒を取るだけで働いてくれてありがとう。あなたの助けに感謝します。 –

0

新しいユーザーの評判のためコメントを追加できません。

テーブルの構造と現在のインデックスが表示されないと、現在のクエリを最適化する方法が分かりません。 質問を編集して、テーブル構造(show create table)を含めてください。

+0

あなたの応答に感謝します。なぜテーブル構造が違うのですか? TABLE_1には98個のフィールドがあり、Customer_Numberはvarchar(20)、TABLE_2には25個のフィールド、cust_noにはvarchar(20)フィールドが設定されています。両方のテーブルには、異なるフィールドに約10の異なるインデックスがあります。 –

+0

私は皆さんが "より良い"変種を持っているのを見ています。私はもっ​​と視覚的な男だと思うし、答えを出す前にこれと一緒にプレイしたいと思っていた。 – Raul

+0

また、そのクエリの説明は、クエリの最も遅い部分がどこにあるかを示している可能性があります。これは、クエリのパフォーマンスをデバッグするときに使用する必要がある情報です。常にその情報も含めてください。 – Raul

関連する問題