2016-01-23 94 views
0

我有兩個查詢在單獨運行時運行得非常快,但是當通過使用其中一個作爲子查詢進行組合時,性能會急劇下降。聯合快速MySQL查詢的性能下降

FAST QUERY I:

SELECT DISTINCT p.products_image, 
       p.products_subimage1, 
       pd.products_name, 
       p.products_quantity, 
       p.products_model, 
       p.products_ordered, 
       p.products_id, 
       p.products_price, 
       p.products_weight, 
       p.products_length, 
       p.products_width, 
       p.products_height, 
       p.products_tax_class_id, 
       p.products_status, 
       IF(s.status, s.specials_new_products_price, NULL)    AS 
       specials_new_products_price, 
       IF(s.status, s.specials_new_products_price, p.products_price) AS 
       final_price 
FROM products p 
     LEFT JOIN specials s 
       ON p.products_id = s.products_id 
     LEFT JOIN products_to_categories p2c 
       ON p.products_id = p2c.products_id 
     LEFT JOIN products_description pd 
       ON p.products_id = pd.products_id 

     LEFT JOIN products_attributes pa 
       ON p.products_id = pa.products_id 
     LEFT JOIN (SELECT `products_id`, 
       `products_stock_attributes`, 
       `products_stock_quantity` 
     FROM products_stock 
     WHERE `products_stock_quantity` > 0) t 
     ON t.products_id = p.products_id 
     WHERE t.products_stock_attributes IN ('1-31', '1-25', '1-18', '1-7') 
     AND p.products_status = '1' 
     AND Date_sub(Curdate(), INTERVAL 30 day) >= p.products_date_added 
     AND pa.options_values_id IN (31, 25, 18, 7) 
GROUP BY p.products_id 
HAVING Count(DISTINCT pa.options_values_id) = 4 
     AND Count(DISTINCT t.products_stock_attributes) = 4 

FAST QUERY II:

SELECT sul2.* 
FROM stock_update_log sul2 
INNER JOIN (SELECT products_id, 
    Max(date_time) AS maxDateTime 
FROM stock_update_log 
WHERE stock_qty_change > 1 
AND id > 154700 
    AND Date_sub(Curdate(), INTERVAL 360 day)<= From_unixtime(date_time) 
GROUP BY products_id)gsul 
     ON sul2.products_id = gsul.products_id 
AND sul2.date_time = gsul.maxdatetime 

合併查詢(非常慢的):

SELECT DISTINCT p.products_image, 
       p.products_subimage1, 
       pd.products_name, 
       p.products_quantity, 
       p.products_model, 
       p.products_ordered, 
       p.products_id, 
       p.products_price, 
       sul.date_time, 
       p.products_weight, 
       p.products_length, 
       p.products_width, 
       p.products_height, 
       p.products_tax_class_id, 
       p.products_status, 
       IF(s.status, s.specials_new_products_price, NULL)    AS 
       specials_new_products_price, 
       IF(s.status, s.specials_new_products_price, p.products_price) AS 
       final_price 
FROM products p 
     LEFT JOIN specials s 
       ON p.products_id = s.products_id 
     LEFT JOIN products_to_categories p2c 
       ON p.products_id = p2c.products_id 
     LEFT JOIN products_description pd 
       ON p.products_id = pd.products_id 
     LEFT JOIN (SELECT sul2.* 
        FROM stock_update_log sul2 
         INNER JOIN (SELECT products_id, 
              Max(date_time) AS maxDateTime 
            FROM stock_update_log 
            WHERE stock_qty_change > 1 
              AND id > 154700 
              AND Date_sub(Curdate(), 
               INTERVAL 360 day) 
               <= 
               From_unixtime(date_time) 
            GROUP BY products_id)gsul 
           ON sul2.products_id = gsul.products_id 
            AND sul2.date_time = gsul.maxdatetime) sul 
       ON p.products_id = sul.products_id 
     LEFT JOIN products_attributes pa 
       ON p.products_id = pa.products_id 
     LEFT JOIN (SELECT `products_id`, 
       `products_stock_attributes`, 
       `products_stock_quantity` 
     FROM products_stock 
     WHERE `products_stock_quantity` > 0) t 
     ON t.products_id = p.products_id 
     WHERE t.products_stock_attributes IN ('1-31', '1-25', '1-18', '1-7') 
     AND p.products_status = '1' 
     AND Date_sub(Curdate(), INTERVAL 360 day) <= From_unixtime(sul.date_time) 
     AND Date_sub(Curdate(), INTERVAL 30 day) >= p.products_date_added 
     AND sul.id > 154700 
     AND sul.stock_qty_change > 1 
     AND pa.options_values_id IN (31, 25, 18, 7) 
GROUP BY p.products_id 
HAVING Count(DISTINCT pa.options_values_id) = 4 
     AND Count(DISTINCT t.products_stock_attributes) = 4 
ORDER BY sul.date_time DESC 

解釋的組合查詢結果: EXPLAIN of combined quries result

我一直在嘗試幾個小時,弄清楚爲什麼它結合他們這麼慢,並試圖重寫組合查詢無濟於事,所以我伸出援手來自這裏的專家。

什麼原因導致它變得如此緩慢,我該怎麼做才能使它變得更快?

回答

1

查詢II感覺它有一百萬行;得到的tmp表沒有索引;它隱藏在LEFT JOIN的後面。儘管如此,優化器似乎足夠聰明,可以從混亂開始,併爲聯合查詢提供7904行。

你能避免LEFT

然後代碼繼續進行,但最終必須從表掃描中檢查所有這些行與18057行。優化器再一次通過使用「連接緩衝區」來做一件聰明的事情。儘管如此,7904 * 923 * 18057還是有很多行。

這似乎是邪惡部分:

LEFT JOIN 
    (SELECT `products_id`, 
       `products_stock_attributes`, 
       `products_stock_quantity` 
     FROM products_stock 
     WHERE `products_stock_quantity` > 0 
    ) t 
    ON t.products_id = p.products_id 

    WHERE t.products_stock_attributes IN ('1-31', '1-25', '1-18', '1-7') 

所有這些似乎是紅旗:(?)

  • 不必要LEFT;
  • 「where attributes in ...」在子查詢之外時,它們可能在裏面;
  • 你或許可以將HAVING Count(DISTINCT t.products_stock_attributes) = 4摺疊到子查詢中。
+0

是的,將'WHERE t.products_stock_attributes IN'和'HAVING Count(DISTINCT t.products_stock_attributes)= 4'移入子查詢解決了這個問題。非常感謝!! :) – CreativeMind

1

您正在連接7個表格,這肯定會很慢。我建議避免加入超過3張桌子。

你有沒有試過自己做兩個查詢,然後結合他們的結果?

+0

Upvoting試圖幫助我。謝謝。 :) – CreativeMind