我有一个包含很多SET语句的存储过程。这需要很长时间才能执行。我可以做些什么来提高性能。我在这里发表了一个声明。
SET @VisitedOutlets=(select count (distinct CustomerId) from dbo.VisitDetail
where RouteId = @intRouteID
and CONVERT(VARCHAR(10),VisitDate,111) between CONVERT(VARCHAR(10),@FromDate,111)
and CONVERT(VARCHAR(10),@ToDate,111));
答案 0 :(得分:0)
我认为您的问题来自您在查询中使用变量的事实。通常,优化器将...优化(!)查询给定(硬编码)值(例如,让id = 123),而不能优化,因为它是变量。
让我们从here:
中汲取一个很好的例子行,
您是优化工具,查询计划是一种工具。
我会给你一个查询,你必须选择车辆。
- 醇>
图书馆中的所有图书都有序号
我的查询是去图书馆并获取3到5之间的所有书籍
你选择一辆正确,快速,便宜,高效且足够大的自行车 带回3本书。
新查询。
进入图书馆,获取@x和@y之间的所有书籍。
选择车辆。
继续。
发生了什么。如果我要书,你会选择自卸卡车吗? 介于1和Maxvalue之间?如果x = 3且y = 5,那就太过分了。 SQL必须 在看到数字之前选择计划。
所以你的问题是优化器无法正常工作。为了让他能够完成自己的工作,您可以让他重新编译或更新统计信息。请参阅here,here和here。
所以我的问题的两个解决方案是:
Recompile:OPTION(RECOMPILE)
Update statistics:EXEC sp_updatestats
答案 1 :(得分:0)
您的查询基本上是:
select @VisitedOutlets= count(distinct CustomerId)
from dbo.VisitDetail
where RouteId = @intRouteID and
CONVERT(VARCHAR(10), VisitDate, 111) between
CONVERT(VARCHAR(10), @FromDate, 111) and CONVERT(VARCHAR(10), @ToDate, 111);
我认为可以优化此查询以利用索引。一个主要问题是日期比较。您不应该对VisitDate
的比较进行任何转换。所以,我会将查询重写为:
select @VisitedOutlets= count(distinct CustomerId)
from dbo.VisitDetail vd
where vd.RouteId = @intRouteID and
vd.VisitDate >= cast(@FromDate as date) and
vd.VisitDate < dateadd(day, 1, cast(@ToDate as date))
对于此查询,您需要VisitDetail(RouteId, VisitDate, CustomerId)
上的索引。我还会以适当的格式存储常量,因此查询本身不需要转换。
between
很危险。 Here是Aaron Bertrand关于这个主题的有趣讨论。