当聚集索引唯一确定的额外列时覆盖索引

时间:2009-12-18 10:21:22

标签: sql-server clustered-index covering-index

假设我需要从luTab更新myTab,如下所示

update myTab
  set LookupVale = (select LookupValue from luTab B
                                       where B.idLookup = myTab.idLookup)

luTab由2列(idLookup(唯一),LookupValue)

组成

哪个更好:idLookup上的唯一聚簇索引,或idLookup和Lookupvalue上的唯一聚簇索引?覆盖指数是否会在这种情况下产生任何影响?

(我最感兴趣的是SQL服务器)


结语:

我跟随Krips测试,在myTab中有27M行,在luTab中有1.5M行。 关键部分似乎是指数的独特性。 如果索引指定为唯一,则更新使用哈希表。 如果未将其指定为唯一,则更新首先通过idLookup(Stream Aggegate)聚合luTab,然后使用嵌套循环。这要慢得多。 当我使用扩展索引时,SQL现在不再被认为LookupValue是唯一的,因此它强制使用更慢,流聚合嵌套的循环路径

2 个答案:

答案 0 :(得分:2)

首先:

  • 覆盖索引始终为非群集
  • 您应始终拥有PK和聚簇索引(SQL Server上默认情况下相同)

这两个概念是分开的

所以:

  • 如果这个唯一标识行
  • ,那么您的PK(群集)将是idLookup
  • 覆盖索引将是(idLookup)INCLUDE(LookupValue)

然而:

  • idLookup是PK(群集),因此您不需要覆盖索引
  • 聚集索引(PK)隐含地“覆盖”聚集索引的性质(简单地说,索引是最低级别的数据)

答案 1 :(得分:1)

我已经创建了你的表并加载了几条记录(50个左右的查找,以及myTab中的15个)。

然后我尝试了各种索引选项。关于luTab的索引搜索总是有29%的成本。

有趣的是,如果将LookupValue列添加到luTab上的索引,则执行计划会在Index Seek:Stream Aggregate和Assert之后显示两个额外步骤。虽然成本为0%,但可能会有更多数据。

我还在idLookup上尝试了非聚集索引,并将LookupValue包含为“包含列”。这样,不需要访问数据页来检索该列。虽然执行计划没有显示任何不同(但它们也没有Stream Aggregate / Assert),这可能是您的选择。

-Krip