【问题标题】:Nonclustered indices: Unique Index including Primary Key vs Non-Unique Index without Primary Key非聚集索引:包含主键的唯一索引与没有主键的非唯一索引
【发布时间】:2017-11-29 09:07:23
【问题描述】:

我用来在表上创建索引的 API 将所有非聚集索引创建为包含主键的唯一索引。

所以给出下表:

CREATE TABLE Person
(
    [PersonID] INT NOT NULL PRIMARY KEY, -- clustered key on this col.
    [First Name] VARCHAR(50),
    [Last Name] VARCHAR(50),
    [Other Columns] VARCHAR(50)
)

API 创建的非聚集索引的 SQL 语句如下所示:

CREATE UNIQUE NONCLUSTERED INDEX KeyName
ON Person ([First Name], [Last Name], [PersonID])

通过在索引中包含主键,可以确保所有条目都是唯一的。

我个人会这样创建索引:

CREATE NONCLUSTERED INDEX KeyName2
ON Person ([First Name], [Last Name])

我在包含大约 2100 万条记录的表上使用了以下语句两次。我一次只激活了一个索引。

SELECT *
FROM Person
WHERE [First Name] = 'John'
AND [Last Name] = 'Doe'

无论启用/禁用哪个索引,“估计 CPU 成本”、“估计 I/O 成本”、“估计算子成本”和“估计子树成本”都完全相同。

我对非聚集索引的理解是,主键不用于检索数据,而是 SQL-Server 独立分配的一些行号。那么使用 UNIQUE 索引而不是 NON-UNIQUE 索引有什么好处吗?

我猜想 UNIQUE 索引会占用更多磁盘空间,因为它包含多列。因此,我更喜欢后一个版本。

使用 SQL-Server 2012

【问题讨论】:

  • Clustered and Nonclustered indexes: "从非聚簇索引中的索引行指向数据行的指针称为行定位器。行定位器的结构取决于...对于聚簇表,行定位器是聚集索引键。”。因此,如果您的 PK 是集群的,那么您对“无论如何都不使用主键来检索数据”的假设是不正确的。

标签: sql sql-server indexing


【解决方案1】:

如果 PersonID 是您的主键,则两者之间没有存储差异

CREATE NONCLUSTERED INDEX KeyName
ON Person ([First Name], [Last Name])

CREATE NONCLUSTERED INDEX KeyName2
ON Person ([First Name], [Last Name], [PersonID])

PersonID 被隐式添加到 KeyName 以标识数据行。

另外

CREATE UNIQUE NONCLUSTERED INDEX KeyName3
ON Person ([First Name], [Last Name], [PersonID)

CREATE NONCLUSTERED INDEX KeyName4
ON Person ([First Name], [Last Name], [PersonID])

在功能上也是相同的。每当主键被显式包含为键列时,该索引在技术上就是唯一索引,即使它仅由主键值强制执行。将唯一限定符添加到 KeyName3 是一种资源浪费,因为 SQL Server 仍然会验证所有三列组合的唯一性,而主键的存在已经保证了这一点。

聚集键包含在每个非聚集索引中以指向聚集索引中的数据行。如果集群键是主键或唯一键,则使用键值来标识数据行。如果集群键不是唯一值,SQL Server 会为每个数据行添加一个唯一值,以便识别它们,尽管这不是真正的行号,因为存在填充以允许插入/删除其他行。该附加值被认为位于显式索引键之后以进行排序。

如果没有聚集索引(堆),则使用隐式唯一值来指向数据行。但是,如果没有索引键来对数据进行排序,行将永远不会改变顺序,因此没有填充,唯一值实际上是一个行号。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-04
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-06
    • 1970-01-01
    相关资源
    最近更新 更多