非聚集索引:唯一索引,包括主键与没有主键的非唯一索引

时间:2017-11-29 09:07:24

标签: sql sql-server indexing

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

所以给出下表:

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

1 个答案:

答案 0 :(得分: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会为每个数据行添加唯一值,以便它可以识别它们,尽管这不是真正的行号,因为有填充以允许插入/删除其他行。该附加值被认为是在用于排序目的的显式索引键之后。

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