2015-07-28 110 views
0

我有一个包含这么多SET语句的存储过程。这需要很长的时间来执行。我能做些什么来提高表现。我在这里列出了一个声明。SQL性能与不同和计数

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

什么是VisitDate,@ FromDate,@ ToDate的数据类型 –

+0

所有3列数据类型都是DATETIME – Tom

+0

您在VisitDetail表中有多少条记录? –

回答

0

我认为你的问题来自你在查询中使用变量的事实。通常,优化器将...优化(!)给定(硬编码)值的查询(比如id = 123),而不能优化,因为它是一个变量。

让我们从here一个很好的例子:

OK,

  1. 你是优化和查询计划是车辆。

  2. 我会给你一个查询,你必须选择车辆。

  3. 所有在图书馆的图书上的序列号

我的查询是去图书馆,让我所有的书3和5

之间你会选择一个合适的自行车,快速,便宜,高效,足以让 带回3本书。

新查询。

转到图书馆,获取@x和@y之间的所有书籍。

挑车。

继续。

这就是发生了什么事。如果我要求书籍 介于1和Maxvalue之间,你会选择自卸车吗?如果x = 3和y = 5,那就太过分了。 SQL必须 在看到数字之前选择该计划。

所以你的问题是优化器不能正确地完成它的工作。为了让他完成他的工作,你可以让他重新编译或更新统计数据。参见here,herehere

所以我的2个解决方案,您的问题将是:

  1. RecompileOPTION(RECOMPILE)

  2. Update statisticsEXEC sp_updatestats

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)) 

对于此查询,您想对​​的索引。我也会以适当的格式存储常量,因此查询本身不需要转换。

between使用日期是危险的。 Here是Aaron Bertrand关于这个话题的有趣讨论。