提高 SQL 查询性能
Posted
技术标签:
【中文标题】提高 SQL 查询性能【英文标题】:Increase SQL Query Performance 【发布时间】:2011-07-20 07:22:27 【问题描述】:Sql:
select distinct DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) as Date,
(select count(*) from Raw_Mats A where DateAdd(Day, DateDiff(Day, 0, A.Receive_date), 0)=DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0)) as Total,
(select count(*) from Raw_Mats B where DateAdd(Day, DateDiff(Day, 0, B.Receive_date), 0)=DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) and B.status='Solved') as Delivered,
(select count(*) from Raw_Mats C where DateAdd(Day, DateDiff(Day, 0, C.Receive_date), 0)=DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) and C.status='Pending') as UnDelivered
from Raw_Mats m where m.Receive_date between '2011-07-01' and '2011-07-21'
如何提高上述查询的性能。它需要 44 秒。想让它少于 10 秒
谢谢
【问题讨论】:
请编辑您的问题。正确标记您的代码 请同时描述您的架构。 您使用的是哪个数据库? mysql? sqlsever? 【参考方案1】:您对Receive_date
和status
都有索引吗? (不是每个的索引,合并)
还有:
您在表中有 4 次触摸,这意味着查询将扩展至少 O(4n)。 通过使用 COUNT(CASE),您可以删除Delivered
和 UnDelivered
子查询
也不需要简单的计数子查询
您需要 GROUP BY。你的 DISTINCT 就是解决这个问题的方法
BETWEEN 是 >=
和 <=
,这对于带时间的日期通常不正确
为了清楚起见,我在这里使用了子查询,但这没关系:
select
DateOnly as Date,
COUNT(*) AS Total,
COUNT(CASE WHEN status='Solved' THEN 1 END) AS Delivered,
COUNT(CASE WHEN status='Pending' THEN 1 END) AS UnDelivered
from
(
SELECT
DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) as DateOnly,
status
FROM
Raw_Mats
WHERE
Receive_date >= '2011-07-01' AND Receive_date < '2011-07-21'
) T
GROUP BY
DateOnly
编辑,没有子查询。
我从一个子查询开始,因为我认为它比预期的要复杂,所以没有费心把它拿出来......
select
DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) as Date,
COUNT(*) AS Total,
COUNT(CASE WHEN status='Solved' THEN 1 END) AS Delivered,
COUNT(CASE WHEN status='Pending' THEN 1 END) AS UnDelivered
from
Raw_Mats
WHERE
Receive_date >= '2011-07-01' AND Receive_date < '2011-07-21'
GROUP BY
DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0)
【讨论】:
一个问题:为什么使用子查询而不是查询表? @niktrs:为了更清楚【参考方案2】:分而治之:只需将 sql 的每个部分作为单独的语句尝试,您就会发现哪个部分慢。如果您有子选择和功能,那么服务器很可能需要临时表来执行选择,如果您没有足够的内存(或大型数据集或配置您的 sql 服务器这样做),这临时对象被交换到磁盘,这也使它变慢。
【讨论】:
【参考方案3】:子查询太多了!摆脱其中的一些,它会有所帮助。此外,你不应该在你的 sqls 中使用两边的函数。
例如:
where DateAdd(Day, DateDiff(Day, 0, A.Receive_date), 0)=
DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0)
在这种特定情况下,数据库引擎必须遍历所有行来评估DateDiff(Day, 0, A.Receive_date) and DateAdd(Day, DateDiff(Day, 0, A.Receive_date), 0)
,然后将其与也是一个函数的右侧进行比较!这简直就是一场灾难。
另外,您在Receive_date
上有索引吗?如果不添加。
【讨论】:
以上是关于提高 SQL 查询性能的主要内容,如果未能解决你的问题,请参考以下文章