0

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

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

luTab 由 2 列组成(idLookup(unique)、LookupValue)

哪个更可取:idLookup 上的唯一聚集索引,还是 idLookup 和 Lookupvalue 上的唯一聚集索引?在这种情况下,覆盖指数会有所作为吗?

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


结语:

我在下面的 Krips 测试中跟进了 myTab 中的 2700 万行,luTab 中的 150 万行。关键部分似乎是索引的唯一性。如果索引指定为唯一,则更新使用哈希表。如果未将其指定为唯一,则更新首先通过 idLookup(流聚合)聚合 luTab,然后使用嵌套循环。这要慢得多。当我使用扩展索引时,SQL 现在不再假定 LookupValue 是唯一的,因此它强制使用慢得多的流聚合嵌套循环路由

4

2 回答 2

2

首先:

  • 覆盖索引始终是非聚集的
  • 您应该始终拥有一个 PK 和一个聚集索引(在 SQL Server 上默认情况下是相同的)

这2个概念是分开的

所以:

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

然而:

  • idLookup 是 PK(聚集),所以你不需要覆盖索引
  • 聚集索引 (PK) 隐含地“覆盖”了聚集索引的性质(简单地说,索引是最低级别的数据)
于 2009-12-18T10:53:33.513 回答
1

我已经创建了您的表并仅加载了几条记录(大约 50 条查找,以及在 myTab 中的 15 条)。

然后我尝试了各种索引选项。luTab 上的 Index Seek 的成本始终为 29%。

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

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

-克里普

于 2009-12-18T10:54:46.007 回答