2010-03-03 84 views
3

我有以下查询:SQL索引问题:为什么SQL Server更喜欢这个非集群索引到一个集群?

SELECT 
    COUNT(*) 
FROM 
    FirstTable ft 
     INNER JOIN SecondTable st ON ft.STID = st.STID 

正如您可以猜到,“STID”是“SecondTable” ......和“FirstTable”主键将有一个指向第二个表。下面是我的指标:

FirstTable:上栏 “STID”

SecondTable非聚集索引:CLUSTERED PRIMARY KEY INDEX的 “STID”

上面的查询给我的19.90子树的成本和花费2秒

运行该查询的数据库调整顾问后,他们建议使与我在第二张表上的索引非常相似......但是非集群索引。所以我尝试了这些结果。

FirstTable:上栏 “STID”

SecondTable非聚集索引:在 “STID” NONCLUSTERED INDEX

现在,上面的查询给我的10.97子树的成本和花费<1秒

这100%破碎了我的大脑......为什么在这种情况下,NONCLUSTERED索引的执行速度比CLUSTERED索引更快?

回答

7

因为您的查询不从表中检索任何实际记录,所以它只是计数。

对于非聚簇索引,它只是连接两个使用最可能的MERGE JOIN的索引(大小比表小)。

对于聚集索引,它必须加入表和非聚集索引。表格较大,需要更多时间来遍历它。

如果发出这样的询问:

SELECT SUM(first_table_field + second_table_field) 
FROM FirstTable ft 
INNER JOIN 
     SecondTable st 
ON  ft.STID = st.STID 

以检索实际值,你会看到集群的好处。

+0

太快了! - 这正是我正在寻找的明确,合乎逻辑的答案。 - 当然,这不是我的*真实*查询,但它确实有助于我真正的查询(不使用该表中的列,而只是将它用于内部联接/过滤) - Thx! – 2010-03-03 12:18:50

+0

@Quassnoi:对不起,这个答案对我来说没有意义。你说:“有了聚集索引,它必须加入表格”。聚集索引是一个索引。原始查询并不真正检索任何列,因此它必须匹配键值,即它只需要扫描索引页。如果您查看这些图片,请https://technet.microsoft.com/en-us/library/ms177443%28v=sql.105%29.aspx和https://technet.microsoft.com/en-us/library /ms177484%28v=sql.105%29.aspx,区别在于,在聚簇索引中,叶节点中有数据,但查询不需要转到叶级别。 – costa 2015-03-23 18:41:57

+0

@quassnoi:继续......除非使用*对查询优化器做了某些事情,并且最好使用count(1)来代替。根据我在SQL Server上的经验,特别是2008年和2008年R2,有时它会做这些你永远不会想到的死脑筋的事情。 – costa 2015-03-23 18:46:37

相关问题