【问题标题】:SQL Performance with Distinct and Count具有 Distinct 和 Count 的 SQL 性能
【发布时间】:2015-10-18 18:19:33
【问题描述】:

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

【问题讨论】:

  • VisitDate,@FromDate,@ToDate的数据类型是什么
  • 所有 3 列数据类型均为 DATETIME
  • VisitDetail 表中有多少条记录?
  • @Tom 然后从 where 子句中删除 convert 函数。同时在Routeidvisitdate 上创建索引
  • 您有关于 CustomerID 的任何索引吗?在包含 customerId 的 RouteID 上添加 NC 索引将提高此查询的性能。

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


【解决方案1】:

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

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

好的,

  1. 您是优化者,查询计划是一辆车。

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

  3. 图书馆的所有书籍都有序号

我的查询是去图书馆,把 3 到 5 之间的所有书拿给我

您会选择合适、快速、便宜、高效且足够大的自行车 带回 3 本书。

新查询。

去图书馆,把@x 和@y 之间的所有书拿来。

选择车辆。

继续。

就是这样。如果我要书,你会选一辆自卸车吗 在 1 和最大值之间?如果 x=3 和 y=5,那就太过分了。 SQL 必须 在它看到数字之前选择计划。

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

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

  1. Recompile : OPTION(RECOMPILE)

  2. Update statistics : EXEC sp_updatestats

【讨论】:

    【解决方案2】:

    您的查询本质上是:

    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 就该主题进行的有趣讨论。

    【讨论】:

      猜你喜欢
      • 2012-12-05
      • 1970-01-01
      • 1970-01-01
      • 2013-01-13
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 2017-12-19
      相关资源
      最近更新 更多