使用带有SQL Server索引的INCLUDE列有什么好处?

Ano*_*op 8 sql performance

CREATE NONCLUSTERED INDEX index_name 
    ON <object> ( column [ ASC | DESC ] [ ,...n ] ) 
    [ INCLUDE ( column_name [ ,...n ] ) ]
    [ WHERE <filter_predicate> ]
Run Code Online (Sandbox Code Playgroud)

在上面的语法中,我们将在INCLUDE中指定非键列.指定非键列有什么好处?

mar*_*c_s 30

假设你有一个像这样的员工表:

CREATE TABLE Employee(EmployeeID INT IDENTITY(1,1) PRIMARY KEY,
                      LastName VARCHAR(50),
                      FirstName VARCHAR(50),
                      HireDate DATETIME,
                      Salary DECIMAL)
Run Code Online (Sandbox Code Playgroud)

您将拥有EmployeeID上的主群集密钥,并且可能在(LastName,FirstName)上具有非群集密钥,以便能够按名称查找雇员.

CREATE INDEX NameIndex ON Employee(LastName ASC, FirstName ASC)
Run Code Online (Sandbox Code Playgroud)

现在,如果您需要找到"Joe Murphy"并检索他的雇用日期和薪水,那么会发生什么是基于名称的非群集密钥(这很好)的索引搜索,但是为了获取雇用日期和薪水,SQL Server需要对实际的表数据进行所谓的书签查找,以获取Joe Murphy的记录.这很可能会导致一个或多个物理磁盘访问(在性能方面不好).

但是:如果基于名称的非聚集索引还指定了"INCLUDE(HireDate,Salary)":

CREATE INDEX NameIndex ON Employee(LastName ASC, FirstName ASC)
       INCLUDE (HireDate, Salary)
Run Code Online (Sandbox Code Playgroud)

一旦查询了Joe Murphy,就会在非聚集名称索引中完成SQL Server - >满足查询的所有字段都在非聚集索引中,因此不再需要进行磁盘密集型书签查找和您的查询可能会更快.

INCLUDE列的缺点是非聚集索引增加了磁盘空间需求,因为它们的叶级节点中将包含列.这是速度和尺寸之间的权衡(像往常一样).


dkr*_*etz 6

使用索引时,它可以指向完整记录的位置,或者您需要的所有字段都可以存储在索引本身中(因此您无需转到完整记录.)

在第一种情况下,您有两个读取最佳案例,一个读取索引,一个读取完整记录.

在第二种情况下,您可以通过阅读索引获得所需的一切.

如果与包含索引的字段一起使用,则可以包含要与索引一起存储的额外列,而不需要对该行进行额外读取即可满足完整查询.

这不是CLUSTERED索引的问题,因为读取索引与读取整行相同.

如果您正在读取序列中的多个索引键(例如,SELECT ... FROM ... WHERE键BETWEEN n1和n2),则会有一个特别大的优点,因为索引读取可能会彼此相邻存储并且可以使用也许只有一两个物理部门; 并且不需要找到其余的记录提供更多的杠杆作用.


tva*_*son 1

这将存储具有索引节点的列的数据,以便对使用索引的查询进行快速访问。

参考

INCLUDE(列 [ ,... n ] )

指定要添加到非聚集索引的叶级别的非键列。非聚集索引可以是唯一的,也可以是非唯一的。