2016-08-16 46 views
0

我有一个简单的select语句需要很长时间才能运行,但在同一个表上运行count(*)相同的WHERE子句在不到一秒的时间内返回。简单的选择查询运行速度非常慢,但在运行速度非常快的同一个表上选择count(*)

这个查询了很长一段时间运行(1小时+):

SELECT col1 
     , col2 
     , col3 
    FROM Table 
    WHERE RowInsertDate >= @SomeStartDate 
    AND RowInsertDate < @SomeEndDate 

但此查询回来在不到一秒钟:

SELECT count(*) 
    FROM Table 
    WHERE RowInsertDate >= @SomeStartDate 
    AND RowInsertDate < @SomeEndDate  

表拥有34万行,具有用于主键的ID列和地理区域(北,南,东,西)列。 “RowInsertDate”列是该行插入到表中的日期。上述查询的预期结果分别为“无行”和“0”。

此表的聚簇索引是(ID,geoRegion)ASC。此表在RowInsertDate ASC上也具有非聚集索引。

我不确定该从哪里出发。有没有人遇到过这个?

+0

可能是一个容量的事情。返回多少行? – Paparazzi

+0

这是一个执行计划可以帮助我们的人。同样,任何人都无法将选择col1,col2与您正在注意的索引关联起来,因为我们不知道索引是否包含或不包含哪些列,所以我们不知道这是否正确或不正确。 – Matt

+0

这两个查询都是不同的,它会导致不同的执行计划。您可以提供执行计划 – TheGameiswar

回答

1

当您运行select count(*)时,SQL Server只能对您的索引中的行进行计数。当您运行select col1,col2,col3时,对于在索引中找到的每一行SQL Server都必须获取聚簇索引键值(ID,geoRegion,存储在索引中),然后使用该聚簇索引键值搜索表中找到的所有行。

如果SQL Server认为为聚簇索引执行所有查找将会更有效,SQL Server也可以决定执行聚簇索引扫描(或其他)。您可以检查查询计划中会发生什么。

为了加快查询速度,您可能需要考虑将需要选择的列添加到RowInsertDate中,包括列或普通列。当然,如果列数相对较少(或者表中不会有很多更新),这当然是有意义的。

0

尽管您可以检查执行计划,但我很确定这是一个典型的BOOKMARK LOOKUP问题。这是资源消耗和耗时。一个解决方案是创建一个涵盖索引来处理它。

这两个查询的执行时间是不同的,因为它们完全不同。

当然,您还应该检查列(col1,col2,col3)的数据类型。

除此之外,您还可以设置NOCOUNT ON。希望能帮助到你。

-2

由于查询非常简单。我认为你缺少的是一个NOLOCK:

SELECT col1 
    , col2 
    , col3 
FROM Table (nolock) 
WHERE RowInsertDate >= @SomeStartDate 
AND RowInsertDate < @SomeEndDate 
+2

这是一个危险的推荐 – Paparazzi

+0

@Paparazzi:对于选择查询nolock是危险的如何? –

+0

@AnjaniKumarAgrawal http://blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere/ – scsimon

0

如果ID是唯一的(如身份证),那么我建议你做的是,PK单独聚。额外的列必须携带额外的数据才能进行查找。

我和我希望geoRegion是一个字节。如果varchar,那么你携带的数量是你需要的10倍。这是相同内存量的1/10。

如果上述不能解决问题然后添加包括在索引

CREATE NONCLUSTERED INDEX IX_Table_RowInsertDate 
ON Table (RowInsertDate) 
INCLUDE (col1, col2, col3); 
0

对不起在响应延迟的那些列。

它看起来像服务器本身有问题;我们的日志充满了IO问题。我们让DBA重新启动服务器,现在查询运行得很快。

我不确定确切问题的性质是什么,但现在已经解决。如果同样的事情再次出现,我会发布另一个问题。

相关问题