2013-10-25 80 views
0

我有以下查詢:如何處理大的MySQL查詢

SELECT p2c.pid AS productNumber, 
     p.name AS productName 
    , (
      SELECT COUNT(*) 
      FROM products2customers 
      WHERE pid = p2c.pid 
     ) AS registered 
    , (
      SELECT COUNT(*) 
      FROM products2customers 
      WHERE pid = p2c.pid 
       AND date_add(from_unixtime(purchased), INTERVAL 5 YEAR) >= CURDATE() 
     ) AS inWarranty 
    , (
      SELECT COUNT(*) 
      FROM products2customers 
      WHERE pid = p2c.pid 
       AND date_add(from_unixtime(purchased), INTERVAL 5 YEAR) < CURDATE() 
     ) AS outOfWarranty 
    , (
      SELECT DATE_FORMAT(MAX(from_unixtime(purchased)), '%d.%m.%Y') 
      FROM products2customers 
      WHERE pid = p2c.pid 
     ) AS lastPurchased 
    , (
      SELECT DATE_FORMAT(date_add(MAX(from_unixtime(purchased)), INTERVAL 5 YEAR), '%d.%m.%Y') 
      FROM products2customers 
      WHERE pid = p2c.pid 
     ) AS warrantyUntil 
FROM (
      SELECT DISTINCT 
       p2c.pid 
      FROM 
       products2customers p2c 
     ) AS p2c 
JOIN 
    products p 
ON 
    p.id = p2c.pid 
ORDER BY 
    inWarranty DESC 

該查詢的數據庫表,其中有25.000行執行。此查詢的執行時間約爲40秒。結果將顯示在網頁上,因此等待40秒的結果並不是很好。

有沒有辦法,執行這個查詢並保存它的輸出?因爲如果每晚都執行此查詢就足夠了。

這樣做的最佳方式是什麼?我應該創建一個cronjob並執行這個查詢並將結果寫入數據庫嗎?或者,還有更好的方法?

或者我可以優化此查詢,使其更快?

+0

如果實時不是你可以使用[MySQL事件]的問題(http://dev.mysql.com/doc/refman/5.1/en/events.html)運行查詢在設定的時間,和'SELECT INTO'來創建一個新的輸出表。然後您可以在這個新表上運行查詢。 – 2013-10-25 06:54:58

回答

2

我認爲所有那些相關的子查詢正在殺死你。試試這個:

SELECT p2c.pid AS productNumber, 
     p.name AS productName, 
     COUNT(*) AS registered, 
     SUM(date_add(from_unixtime(purchased), INTERVAL 5 YEAR) >= CURDATE()) AS inWarranty, 
     SUM(date_add(from_unixtime(purchased), INTERVAL 5 YEAR) < CURDATE()) AS outOfWarranty, 
     DATE_FORMAT(MAX(from_unixtime(purchased)), '%d.%m.%Y') AS lastPurchased, 
     DATE_FORMAT(date_add(MAX(from_unixtime(purchased)), INTERVAL 5 YEAR), '%d.%m.%Y') AS warrantyUntil 
FROM products2customers p2c 
JOIN products p ON p.id = p2c.pid 
GROUP BY p2c.pid 
ORDER BY inWarranty DESC 
+0

嘿巴爾瑪,很高興看到我的SQL上帝。 ;-) Baaam,你的查詢254ms。感謝您再次幫助我。 ;-)你可以請發佈這個答案也在這個問題:http://stackoverflow.com/questions/19496642/mysql-counting-rows-with-loop因爲我認爲你的解決方案是迄今爲止最好的。 :)感謝和來自德國的問候。 ;-) – emjay

+0

嘿@Barmar,看起來outOfWarranty不算數。我將我的長查詢與您的數據進行了比較,並檢查了表中的數據。你能檢查你的答案嗎? – emjay

+0

如果'> ='它應該是'<'。 – Barmar

1

也許首先通過執行Explain Plan來查看是否可以通過創建索引來加速任何部分。

1

將這個變成一個cron作業:

CREATE TABLE products_warrany SELECT p2c.pid AS productNumber, ... 

以後使用下面的查詢,而不是原來的長單:

SELECT * FROM products_warrany ORDER BY ... 

您還可以獲得運行額外的過濾,排序等功能。 Reference.