CREATE NONCLUSTERED INDEX index_name
ON <object> ( column [ ASC | DESC ] [ ,...n ] )
[ INCLUDE ( column_name [ ,...n ] ) ]
[ WHERE <filter_predicate> ]
在上面的语法中,我们将在INCLUDE中指定非键列。指定非键列有什么好处?
答案 0 :(得分:30)
假设你有一个像这样的员工表:
CREATE TABLE Employee(EmployeeID INT IDENTITY(1,1) PRIMARY KEY,
LastName VARCHAR(50),
FirstName VARCHAR(50),
HireDate DATETIME,
Salary DECIMAL)
您将在EmployeeID上拥有主群集密钥,并且可能在(LastName,FirstName)上拥有非群集密钥,以便能够按名称查找雇员。
CREATE INDEX NameIndex ON Employee(LastName ASC, FirstName ASC)
现在,如果您需要找到“Joe Murphy”并检索他的雇佣日期和薪水,那么会发生什么是基于名称的非群集密钥(这很好)的索引搜索,但是为了获取聘用在日期和工资方面,SQL Server需要对实际的表数据进行所谓的书签查找,以获取Joe Murphy的记录。这很可能会导致一次或多次物理磁盘访问(性能方面不好)。
但是:如果基于名称的非聚集索引还指定了“INCLUDE(HireDate,Salary)”:
CREATE INDEX NameIndex ON Employee(LastName ASC, FirstName ASC)
INCLUDE (HireDate, Salary)
然后SQL Server在非群集名称索引中查找Joe Murphy时完成 - &gt;所有满足查询的字段都在非聚集索引中,因此不再需要进行磁盘密集型书签查找,您的查询可能会更快。
INCLUDE列的缺点是非聚集索引增加了磁盘空间需求,因为它们的叶级节点中将包含列。这是速度和尺寸之间的权衡(像往常一样)。
马克
答案 1 :(得分:6)
当使用索引时,它可以导致完整记录的位置,或者您需要的所有字段都可以存储在索引本身中(因此您不需要去完成记录。)
在第一种情况下,您有两个读取最佳案例,一个读取索引,一个读取完整记录。
在第二种情况下,您可以通过阅读索引获得所需的一切。
如果与包含索引的字段一起,您可以包含要与索引一起存储的额外列,您可以满足完整查询,而无需对该行进行额外读取。
对于CLUSTERED索引,这不是问题,因为读取索引与读取整行相同。
如果您正在读取序列中的多个索引键(例如,SELECT ... FROM ... WHERE键BETWEEN n1和n2),则有一个特别大的优点,因为索引读取可能会彼此相邻存储并且可以或许只有一个或两个物理部门阅读;并且不需要找到其余的记录提供了更多的杠杆作用。
答案 2 :(得分:1)
这将存储具有索引节点的列的数据,以便快速访问使用索引的查询。
INCLUDE(列[,... n])
指定非键列 添加到叶子的水平 非聚集索引。非聚集的 index可以是唯一的也可以是非唯一的。
答案 3 :(得分:0)
如果查询使用包含的列,则无需执行键查找。实施例。
select ssn, firstname from myusers where ssn='111-11-1111'
适当的索引看起来像这样
create index idx_user_ssn nonclustered on myusers(ssn) include(firstname)
答案 4 :(得分:0)
包含索引的优点是避免大小限制。
SELECT AddressLine1, AddressLine2, City, StateProvinceID, PostalCode
FROM Person.Address
WHERE PostalCode BETWEEN N'98000' and N'99999'
虽然您可以将所有列定义为键列,但密钥大小将为334个字节。我们在此使用的唯一标准是Postalcode,在密钥列中使用Postalcode并在非键列上休息将提高性能并且还保存大小。
CREATE INDEX IX_Address_PostalCode
ON Person.Address (PostalCode)
INCLUDE (AddressLine1, AddressLine2, City, StateProvinceID);