2012-12-08 136 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