2016-12-15 62 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包含28000條記錄(CUSTOMER_NUMBER領域是獨一無二的,編入索引建)

TABLE_2包含25萬條記錄(CUST_NO不是唯一的,但編入索引建)

它就是更新TABLE_1通過加入Table_2並使用子查詢總結TABLE_2中兩年的總銷售額值,然後將值更新回TABLE_1 WHERE TABLE_1定製員編號與TABLE_2 Cust_no匹配。

+2

用'EXPLAIN'運行查詢併發布輸出。這將顯示哪部分查詢很昂貴。 –

回答

3

我可以想到一些可能的解決方案。

方法一

只做一個子查詢,沒有做任何相關子查詢,並和有條件基於一年。

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; 

方法二

都做不子查詢。

首先,零出總銷量爲所有客戶:

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

然後做一個連接,而無需使用任何子查詢或SUM()電話,一次添加每個銷售數字一到總銷售額爲客戶。

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,年銷售)在TABLE_2的指標。


在此期間,我可以解釋一下爲什麼您原來的查詢太慢了。你的子查詢讀取TABLE_2,你說它有250,000行(我假設所有行都在2015-2016),並且每行都計算相應客戶的總銷售額。這意味着它會爲每個客戶多次計算相同的金額。

您正在運行500,000個相關的子查詢!這實際上是一個奇蹟,它只需要12分鐘。

因爲這樣做,它將整個結果保存在250,000行臨時表中,因爲子查詢。

然後它將臨時表加入TABLE_1,併爲每個客戶設置CY_TOTAL_SALES和PY_TOTAL_SALES。你不知道,但它爲每個客戶設置了多次相同的總數。

+0

謝謝,並會嘗試你的解決方案,看看。 –

+1

嗨比爾,感謝您的詳細解釋和方法,一個工作最好只需要1.2秒。非常感謝你的幫助。 –

0

由於新的用戶信譽,無法添加註釋。

沒有看到表結構和當前索引將很難分辨如何優化您當前的查詢。 請編輯您的問題以包含表格結構(show create table)。

+0

感謝您的回覆,爲什麼表格結構有所不同? TABLE_1有98個字段,Customer_Number被設置爲varchar(20),TABLE_2有25個字段,字段cust_no也被設置爲varchar(20)。這兩個表在不同領域有大約10個不同的索引。 –

+0

我看到你們得到了一個「更好」的變體 - 我同意Bill對這個問題的看法。我想我更像是一個視覺化的人,並且想在我給出答案之前在我的最後玩這個。 – Raul

+0

此外,該查詢的解釋可能會告訴你查詢的最慢部分在哪裏。這是調試查詢性能時需要使用的最有用的信息 - 始終也包含這些信息! – Raul