SQL Server:类似查询的不同执行计划和性能
Posted
技术标签:
【中文标题】SQL Server:类似查询的不同执行计划和性能【英文标题】:SQL Server : different execution plan and performance for similar queries 【发布时间】:2017-03-20 19:52:51 【问题描述】:我在同一张表上有 2 个查询,我预计性能相似,但我仍然得到了巨大的差异 - 30 秒与 ~ 1 秒。
查询1:统计当月用户数
SELECT datepart(year,getdate()) as TheYear,
DATEPART(month, GETDATE()) AS TheMonth,
COUNT(DISTINCT Username) AS TheUsers
FROM dbo.[AP-Data]
WHERE datepart(year,RequestDate) = datepart(year,getdate())
AND datepart(month,RequestDate) = datepart(month,getdate())
查询 2:统计本周的用户数
SELECT datepart(year,getdate()) as TheYear,
DATEPART(week, GETDATE()) AS TheWeek,
COUNT(DISTINCT Username) AS TheUsers
FROM dbo.[AP-Data]
WHERE datepart(year,RequestDate) = datepart(year,getdate())
AND datepart(week,RequestDate) = datepart(week,getdate())
该表有大约 350 万条记录,并由 RequestDate
索引。本月的计数正在执行全表扫描,因此需要 30 秒,一周的计数在 ~ 1 秒内执行 RID 查找 - 此信息来自执行计划。
知道为什么会有差异吗?
【问题讨论】:
对某些东西是否支持 SARG 进行一些研究。如果您在 join 或 where 子句中的列上使用函数,通常无法在其上利用索引。 您根本不应该在WHERE
上使用DATEPART(something,RequestDate)
。尝试重写它们以使用类似:WHERE RequestDate >= CONVERT(VARCHAR(6),GETDATE(),112) + '01'
或类似的东西
谢谢,我试过了,结果也很奇怪:'SELECT COUNT(DISTINCT Shortname) AS TheUsers FROM dbo.[AP-Data] WHERE RequestDate > '2017-03-01' 运行在一秒。但是 SELECT COUNT(DISTINCT Shortname) AS TheUsers FROM dbo.[AP-Data] WHERE RequestDate > CONCAT(datepart(year,getdate()),'-0',datepart(month,getdate()),'-01')运行时间为 30 秒。
【参考方案1】:
试试这些查询怎么样?
SELECT year(getdate()) as TheYear, month(GETDATE()) AS TheMonth,
COUNT(DISTINCT Username) AS TheUsers
FROM dbo.[AP-Data]
WHERE RequestDate >= dateadd(month, datediff(month, 0, getdate()), 0);
和:
SELECT year(getdate()) as TheYear, month(GETDATE()) AS TheMonth,
COUNT(DISTINCT Username) AS TheUsers
FROM dbo.[AP-Data]
WHERE RequestDate >= dateadd(week, datediff(week, 0, getdate()), 0);
在列上使用函数通常会阻止编译器使用索引。以上假设您没有未来的请求日期。
【讨论】:
它们都在 1 秒内工作。在我的初始查询中,这只是一周工作正常,我仍然有兴趣了解差异来自哪里。 同样试图获取上个月的 COUNT,但它不起作用(快):SELECT year(getdate()) as TheYear, month(GETDATE()) AS TheMonth, COUNT(DISTINCT Username) AS TheUsers FROM dbo.[AP-Data] WHERE RequestDate >= dateadd(month, datediff(month, 0, getdate())-1, 0) AND RequestDate < dateadd(month, datediff(month, 0, getdate()), 0);
以上是关于SQL Server:类似查询的不同执行计划和性能的主要内容,如果未能解决你的问题,请参考以下文章
强制SQL Server执行计划使用并行提升在复杂查询语句下的性能
sql server 执行计划(execution plan)介绍