使用聚合函数优化 MySQL 视图

Posted

技术标签:

【中文标题】使用聚合函数优化 MySQL 视图【英文标题】:Optimizing MySQL View with aggregate function 【发布时间】:2012-12-08 08:27:59 【问题描述】:

我有这样的看法:

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 秒才能完成。

还有其他方法可以优化这个查询吗?

【问题讨论】:

mysql VIEW as performance troublemaker 【参考方案1】:

我认为没有必要加入这些表,只需分组 order 就足够了。 (只是我的观点)。像这样:

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

然后你可以和其他人一起加入这个视图。并在order 上使用索引。

【讨论】:

表格发票包含客户姓名、电话等其他信息 试试这样:select i.id, i.customer_name, i.tel, ir.total from invoice i join invoicereport ir on ir.id = i.id【参考方案2】:

我同意 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

【讨论】:

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

以上是关于使用聚合函数优化 MySQL 视图的主要内容,如果未能解决你的问题,请参考以下文章

26《MySQL 教程》聚合函数(聚合函数 MIN、MAX)

MySQL窗口函数_聚合函数

MySQL函数的聚合函数

MySQL聚合函数

MySQL 聚合函数聚合(组合)函数概述

mysql之聚合函数