查询过于密集,服务器无法在5000条记录上执行

时间:2013-01-28 10:51:00

标签: mysql

我有一个查询,根据所涉及的销售,销售项目和员工构建一行销售信息。它在我的开发服务器上运行良好,10-20销售,但是当在具有5,000+销售额的终端服务器上运行时,它会使整个系统停止运行。

SELECT Sales.SaleID,
Sales.StaffID,
Sales.CustomerID,
Sales.Timestamp,
Sales.Refunded,
Sales.PaymentType,
Staff.Forename AS staffForename,
Staff.Surname AS staffSurname,
itemList, sumOfCost,
sumOfPrice,
a.sumOfPrice - a.sumOfCost AS sumOfProfit

FROM Sales
INNER JOIN Staff ON Sales.StaffID = Staff.StaffID
LEFT JOIN (
              SELECT SaleID,
              GROUP_CONCAT(Quantity, ' x ', Name) itemList,
              SUM(Cost*Quantity) sumOfCost, SUM(Price*Quantity) sumOfPrice
              FROM SaleItems GROUP BY SaleID
          ) a
ON a.SaleID = Sales.SaleID

WHERE Sales.Deleted = '0'
AND Sales.ShopID = '0'
ORDER BY Sales.Timestamp DESC LIMIT 0,15

非常感谢任何帮助!此查询的最后一次尝试耗时65秒......

2 个答案:

答案 0 :(得分:0)

我只是疯了,还是这就是我需要的?

SELECT Sales.SaleID,
Sales.StaffID, 
Sales.CustomerID, 
Sales.Timestamp, 
Sales.Refunded, 
Sales.PaymentType, 
Staff.Forename AS staffForename, 
Staff.Surname AS staffSurname, 
GROUP_CONCAT(SaleItems.Name) AS ItemList, 
SUM(Cost) AS sumOfCost, 
SUM(Price) AS sumOfCost, 
SUM(Price) - SUM(Cost) AS sumOfProfit 
FROM Sales 
JOIN Staff ON Sales.StaffID = Staff.StaffID 
JOIN SaleItems ON Sales.SaleID = SaleItems.SaleID 
WHERE Sales.Deleted = '0' 
AND Sales.ShopID = '0' 
GROUP BY SaleItems.SaleID 
ORDER BY Sales.Timestamp DESC 
LIMIT 0,15

它似乎给出了正确的结果,但似乎没那么令人费解,因此我之前没有看到它有点混乱?

答案 1 :(得分:0)

首先,您没有子查询(在我看来)。对我来说,子查询是依赖于查询中另一个表的记录并且针对每一行进行处理的子查询。您的版本只是运行一次完整查询,获得完整的结果集,然后将其作为连接到其他表的基础。

接下来,所有表格都应该有其他人评论中所述的明显索引,例如处理所有JOIN条件(加入员工ID,销售ID等)。但是,您还应该有一个索引来帮助优化您的标准......在这种情况下,我会有一个索引

(Deleted, ShopID, SaleID )

包含“SaleID”列的原因是用于优化GROUP BY和ORDER BY子句。看起来你只想要最近的15次销售。由于时间戳将直接与销售交易相关联,因此意味着SaleID#1在SaleID#2之前具有时间戳,依此类推销售ID#3,#4,#5。也就是说,我只需通过销售ID DESCENDING获得相同结果的订单。

现在,为您的查询。您最初拥有的是一个预先查询,它汇总了所有销售,每个项目的各自成本和价格。这可能就是在扼杀你的表现。您只会丢弃所有不符合最外层WHERE标准的记录。

所以现在你知道我来自哪里,我会做以下事情。我的“PreQuery”只是从销售表中选择,以获得最近15个已删除和商店ID标准的销售额,但按销售ID降序排序(与上述示例的时间戳基本相同)......将其限制为15.然后,完成您的加入和分组,这样您只会汇总与15个销售相关的订单项,而不是整个销售数据库。由于“PreQuery”已预先订购了最新版本,因此我们无需重新排序外部结果集。

我需要将分组保持在外层,因为您可以为单个销售ID提供10个订单项,并且只想显示该销售的最终总计条目。

    SELECT 
          S.SaleID,
          S.StaffID,
          S.CustomerID,
          S.Timestamp,
          S.Refunded,
          S.PaymentType,
          Staff.Forename AS staffForename,
          Staff.Surname AS staffSurname,
          GROUP_CONCAT(SI.Quantity, ' x ', SI.Name) itemList,
          SUM(SI.Cost*SI.Quantity) sumOfCost, 
          SUM(SI.Price*SI.Quantity) sumOfPrice,
          SUM(SI.Price*SI.Quantity) - SUM(SI.Cost*SI.Quantity) AS sumOfProfit
       FROM 
          ( select Sales.SaleID
               FROM Sales
               WHERE Sales.Deleted = '0'
                  AND Sales.ShopID = '0'
               ORDER BY 
                  Sales.SaleID DESC 
               LIMIT 
                  0,15 ) PreQuery
             JOIN Sales S
                on PreQuery.SaleID = S.SaleID
                JOIN SaleItems SI
                   ON Sales.SaleID = SI.SaleID
                JOIN Staff 
                   ON S.StaffID = Staff.StaffID
   group by
      S.SaleID