具有独特性和计数的SQL性能

时间:2015-07-28 09:18:00

标签: sql sql-server stored-procedures sql-server-2005

我有一个包含很多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)); 

2 个答案:

答案 0 :(得分:0)

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

让我们从here

中汲取一个很好的例子
  

行,

     
      
  1. 您是优化工具,查询计划是一种工具。

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

  4.   
  5. 图书馆中的所有图书都有序号

  6.         

    我的查询是去图书馆并获取3到5之间的所有书籍

         

    你选择一辆正确,快速,便宜,高效且足够大的自行车   带回3本书。

         

    新查询。

         

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

         

    选择车辆。

         

    继续。

         

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

所以你的问题是优化器无法正常工作。为了让他能够完成自己的工作,您可以让他重新编译或更新统计信息。请参阅hereherehere

所以我的问题的两个解决方案是:

  1. RecompileOPTION(RECOMPILE)

  2. Update statisticsEXEC 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关于这个主题的有趣讨论。