2011-11-29 53 views
7
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' 

是否索引查找

在此先感谢。

+0

#TaxInvoiceData中有多少行? – Joe

+0

*是否索引寻找* - 好的,但在**哪个索引** ???另外:你说'(ID,Field2,Field3)'是你的'表X'上的主键 - 是表上的**聚集索引**吗?或者这是一个堆? –

+0

S如何加入查询?这可能是因为主键没有被聚集,所以扫描表比在每一行的索引和表之间跳转要快。 – idstam

回答

5

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

但是,让我们尝试阅读优化器的思想。

由于您没有提供完整的表格模式,因此我假定xxx.ID上有一个聚簇索引,而#TaxInvoiceData是一个堆。您期待的计划是在#TaxInvoiceData中的每一行探索PK索引,但是您选择xxx.Field4这将需要为每个匹配查找书签。这可能导致29,000个随机I/O请求。哎哟。相反,SQL Server可能(而且显然会)只是执行更大​​量的更有效的顺序I/O来完成表扫描,并且可能会对#TaxInvoiceData进行快速哈希匹配。

那么你能做什么?您可以创建一个覆盖索引,包括Field4。或者你可以使用索引和加入提示来强制你正在寻找的计划(但我怀疑绩效不会如你所愿)。这个查询的使用频率是否足够高,以至于它给你的应用程序性能带来问题,或者你只是想从原理上消除表扫描?如果是后者,你可能会发现摆脱扫描的开销并不值得。


编辑:

既然你已经提到,在桌子上没有聚集索引,这也可能会影响从索引中查找有效的。除非此表格看到插入活动过重,否则请考虑将您的PK更改为聚簇。只有这一点可能会改变计划,即使它不会加速其他业务,也可能因为开销减少而加速。

+0

感谢您的解释,人们同意。但请原谅我的无知,我不明白为什么Field4有所作为,因为它是select而不是where子句,我认为它会像这样工作,通过where子句找到page/row/leaf并从那里获取字段行。所以我不理解Field4的索引如何改进搜索。此外,没有聚集索引仅仅是出于任何原因被设置为非聚集的PK。 – Mike

+5

如果查询所需的所有内容都包含在索引中,则SQL Server可以只查看它并避免完全使用该表。这被称为查询的“覆盖索引”,通常非常有效。情况并非如此,因为必须从表中读取Field4。问题的原因在于,由于I/O开销,重复(数千次)在索引行引用的表中查找行的效率不高。优化器在决定做什么时正在考虑所有这些。 – zinglon

-2

可能重写查询将有助于:

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

感谢您的时间,但这并没有改变查询计划。 – Mike

+6

这不是标准的'JOIN'语法,以这种方式重写查询应该没有影响*和*使代码变得更糟,-1 – Matthew

相关问题