【问题标题】:Does an index already cover a clustered primary key?索引是否已经覆盖了聚集的主键?
【发布时间】:2011-07-01 18:26:56
【问题描述】:

假设我有一张这样的桌子:

CREATE TABLE t(
  [guid] [uniqueidentifier] NOT NULL,
  [category] [nvarchar](400)
  {,...other columns}
  )

guid 是我的主键,并且有一个聚集索引。

现在,我想要一个涵盖 categoryguid 的索引,因为我正在按类别汇总与 t 相关的一些其他内容,并且我想避免包括t 表本身。

创建覆盖category 的索引是否足够,或者我还需要包含guid

我希望 SQL Server 索引直接指向 t 中的页面偏移量,而不是简单地引用 guid 主键值,这意味着我需要显式包含 PK 列避免碰到t。是这样吗?

【问题讨论】:

    标签: sql-server tsql indexing


    【解决方案1】:

    实际上您的假设是错误 - 所有 SQL Server 非聚集索引都包含 聚集键(单列或多列)并且 > 直接指向某个物理页面。

    当页面需要一分为二或重新定位时,这可以防止 SQL Server 必须重新组织和更新大量索引条目。因此,如果您在非聚集索引中查找并找到一个值,那么您拥有聚集键,SQL Server 将需要执行“书签查找”(或键查找)来检索实际数据页(叶页在聚簇索引中)来获取属于单行的整组数据。

    也就是说 - 如果您曾经遇到过依赖于键列的顺序的情况,那么您仍然可能需要专门在 (guid, category) 上创建索引 - 当然,在这种情况下,SQL Server 足够聪明找出集群键列已经在索引中并且不会再添加它。

    集群键列包含在每个非聚集索引中的事实是集群键应该是窄的、静态的和唯一的另一个重要原因。让它们太宽(超过 8 字节)肯定会导致膨胀和减速。

    【讨论】:

    • 谢谢马克!我以为我在解释执行计划时要发疯了。有道理的是,索引不应该与页面指针混在一起,即使具有避免书签查找的微小性能优势。关于订购也很好。
    【解决方案2】:

    与 marc_s 的回答略有不同。

    (category, guid) 上的覆盖索引在 GUID 上的排序与主键排序不同。因此,guid 可能会在索引中出现两次,因为它在键列列表和指向聚集索引的指针中。

    如果您包含(作为非键列)guid SQL Server 将不会再次添加它。

    我刚才不能测试key column的东西,但是我之前已经在SQL Server 2005上验证过INCLUDE了。

    【讨论】:

      猜你喜欢
      • 2018-08-04
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      • 2012-12-21
      • 2019-05-30
      • 1970-01-01
      相关资源
      最近更新 更多