为什么要执行表扫描?

时间:2011-11-29 15:51:47

标签: sql sql-server indexing

SELECT X.ID, X.Field4
FROM 
        #TaxInvoiceData T
INNER JOIN
        xxx X
        ON  T.Id = X.Id
        AND Field2 = @VAR     
        AND Field3 = 'S'

当我在表X上运行查询全表扫描时。我不明白为什么因为表X的主键是

ID INT ASC
Field3 CHAR(2) ASC
Field2 DATETIME ASC  Unique Non-clustered

上还有一个索引
Field2 DATETIME ASC  Non-Unique Non-clustered

只做

SELECT ID
FROM xxx
WHERE 
    Field2 = @VAR   
AND Field3 = 'S'

索引是否正在寻求

提前致谢。

2 个答案:

答案 0 :(得分:5)

简短回答:因为优化器认为它会更快。

但是,让我们试着阅读优化器的想法。

由于您还没有提供完整的表模式,我将假设xxx.ID上有一个聚簇索引,而#TaxInvoiceData是一个堆。您期望在#TaxInvoiceData中针对每一行探测PK索引的计划,但您选择xxx.Field4,这将需要为每个匹配查找书签。这可能导致29,000个随机I / O请求。哎哟。

相反,SQL Server可以(并且显然会)执行更大量的更高效的顺序I / O进行表扫描,并且可能正在对#TaxInvoiceData进行快速哈希匹配。

那你能做什么?您可以创建包含Field4的覆盖索引。或者您可以使用索引和联接提示来强制您正在寻找的计划(但我怀疑性能不会像您希望的那样好)。此查询是否经常使用,以至于它会给您的应用程序性能问题,或者您只是想在原则上消除表扫描?如果是后者,你可能会发现摆脱扫描的开销最终不值得。


编辑:

由于您已经提到表中没有聚簇索引,这也可能会影响索引的查找效率。除非此表看到非常繁重的插入活动,否则请考虑将PK更改为群集。仅这一点可能会改变计划,即使它没有,也可能因为减少开销而加速其他操作。

答案 1 :(得分:-2)

也许重写查询会有所帮助:

SELECT X.ID, X.Field4 
FROM  xxx X,  #TaxInvoiceData T 
WHERE X.Id = T.Id        
AND X.Field2 = @VAR              
AND X.Field3 = 'S'