2012-12-08 135 views
2

MySQL視圖我有這樣的看法:優化與聚合函數

CREATE VIEW invoicereport 
SELECT i.ID, SUM(o.Amount * o.Price) AS Total 
FROM invoice i 
JOIN `order` o ON i.ID = o.InvoiceID 
GROUP BY i.ID 

運行此查詢直接將0.03秒。 但運行視圖需要2秒。即使當我做SELECT * FROM invoicereport WHERE ID=9000它仍然需要2秒。

所以我重寫視圖:

CREATE VIEW invoicereport 
SELECT i.ID, (SELECT SUM(Amount * Price) FROM `order` WHERE InvoiceID=i.ID) AS Total 
FROM invoice i 

以爲子查詢只用於ID 9000 執行然後當我做SELECT * FROM invoicereport WHERE ID=9000也就更慢,需要3秒完成。

是否有任何其他方式來優化此查詢?

+2

[MySQL視圖作爲性能搗亂](http://www.mysqlperformanceblog.com/2007/08/12/mysql-view-as-performance-troublemaker/) –

回答

0

我認爲沒有必要加入這些表格,只需將order分組就足夠了。 (只是我的觀點)。像這樣:

CREATE VIEW INVOICEREPORT 
SELECT O.INVOICEID as ID, SUM(O.AMOUNT * O.PRICE) AS TOTAL 
FROM `ORDER` O 
GROUP BY O.INVOICEID 

然後你可以加入這個觀點與他人。並使用order上的索引。

+0

表發票包含其他信息,例如客戶姓名,電話等 – mumu

+0

嘗試這樣的: '從發票選擇i.id,i.customer_name,i.tel,ir.total 我 上ir.id = i.id' –

+0

這花了加盟invoicereport IR 2秒,大約與第一個代碼相同 – mumu

0

我同意Kuya John的評論。在這樣一個簡單的總結中,甚至不打算將它作爲一個觀點來做。它的簡單性沒有必要進行連接。還有另一個答案,我提供了幾年後類似的地方,有人使用現有的觀點,他的查詢是一些淫穢的時間。當我要求回到查詢的原始表並直接寫入時,查詢仍然非常簡單,而且非常快速。不要使用視圖,只要有直接的選擇語句。

類似於子選擇的視圖是典型的查詢時間殺手,我儘量避免它們兩個。

因爲您也在尋找其他發票數據,所以應該沒有問題......但確認量更大......您的訂單表是否在發票ID上有一個索引?

SELECT 
     I.ID, 
     I.Customer_Name, 
     I.Tel, 
     SUM(o.Amount * o.Price) AS Total 
    FROM 
     invoice I 
     JOIN `order` o ON I.ID = O.InvoiceID 
    WHERE 
     I.ID = 9000 
    GROUP BY 
     I.ID 
+0

InvoiceID是一個索引。此外,實際查詢比這更復雜,它包含COUNT(o.ID)AS OrderCount,SUM(IF(mg.Type ='Food',1,0))AS FoodCount,SUM(IF(mg.Type = 'Drink',1,0))AS DrinkCount等等,而'order'加入''menu'加入'menugroup' – mumu