【问题标题】:General SQL Query Performance一般 SQL 查询性能
【发布时间】:2015-05-21 18:54:59
【问题描述】:

我有一张大而薄的桌子,用来记录在活动上花费的时间。

两个表存在活动和记录时间。 Recorded Time 包含一个日期戳,表示所用时间的日期。

我需要获取在某个日期范围内仅记录时间的活动列表。

目前我有构建排除列表并将这些活动存储到临时表中的代码:

DECLARE @DontInclude TABLE (ActivityID INT)

INSERT INTO @DontInclude
 SELECT DISTINCT ActivityID
 FROM RecordedTime
 WHERE DateStamp < @StartDate

INSERT INTO @DontInclude
 SELECT DISTINCT ActivityID
 FROM RecordedTime
 WHERE DateStamp > @EndDate

这样做的问题是,很多数据位于小日期范围之外,因此时间很长。

我不能使用 BETWEEN,因为它不会带回在特定日期范围内记录时间的活动。

我已经查看了 Estimate Execution Plan 并创建了 SQL 建议的所有索引。

我的这部分 SP 仍然是瓶颈。任何人都可以建议我可以进行哪些其他更改来提高性能?

【问题讨论】:

  • 只是出于好奇,为什么您的@StartDate 大于您的@EndDate?

标签: sql sql-server performance tsql


【解决方案1】:

您想要的查询听起来像这样:

select a.*
from activities a
where not exists (select 1
                  from RecordedTime rt
                  where rt.activityId = a.activityId and
                        dateStamp < @StartDate
                 ) and
      not exists (select 1
                  from RecordedTime rt
                  where rt.activityId = a.activityId and
                        dateStamp > @EndDate
                 ) and
      exists (select 1
              from RecordedTime rt
              where rt.activityId = a.activityId 
             );

为了提高性能,您需要在RecordedTime(activityId, datestamp) 上建立索引。

请注意,使用三个子查询是有意的。每个子查询都应该充分利用索引,因此查询应该相当快。

【讨论】:

  • 除此之外,当表变量包含“大量”记录时,它们的性能比临时表差。
【解决方案2】:

您可以将插入语句组合到一个查询中以使其更有效,如下所示:

DECLARE @DontInclude TABLE (ActivityID INT)

INSERT INTO @DontInclude
 SELECT DISTINCT ActivityID
 FROM RecordedTime
 WHERE DateStamp < @StartDate OR Datestamp > @EndDate

当然,就像@Gordon Linoff 提到的那样,在 recordedtime 表上添加非聚集索引会使其更快!

【讨论】:

    【解决方案3】:

    首先收集范围内的列表,然后删除应该排除的列表:

    SELECT DISTINCT tmpId = r.ActivityID
    INTO #tmp
    FROM RecordedTime r
    WHERE r.DateStamp >= @StartDate and r.DateStamp < @EndDate
    
    DELETE FROM #tmp
    WHERE exists(select 1 from RecordedTime r 
                 where r.ActivityID = tmpID
                 and (r.DateStamp < @startDate or
                      r.DateStamp > @endDate))
    

    这应该会更快,因为您只检查可能包含的排除条件(“不存在”);而不是对表中的所有内容运行“不存在”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-05
      • 2016-12-06
      相关资源
      最近更新 更多