【问题标题】:What is the advantage of using an INCLUDE column with a SQL Server index?将 INCLUDE 列与 SQL Server 索引一起使用有什么好处?
【发布时间】:2009-05-03 22:44:43
【问题描述】:
CREATE NONCLUSTERED INDEX index_name 
    ON <object> ( column [ ASC | DESC ] [ ,...n ] ) 
    [ INCLUDE ( column_name [ ,...n ] ) ]
    [ WHERE <filter_predicate> ]

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

【问题讨论】:

    标签: sql performance


    【解决方案1】:

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

    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 后完成 --> 满足您查询的所有字段都在非聚集索引中,因此不再需要执行磁盘密集型操作书签查找和您的查询可能会更快。

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

    马克

    【讨论】:

    • 很好的解释...非常感谢
    【解决方案2】:

    当使用索引时,它既可以导致完整记录的位置,也可以将您需要的所有字段存储在索引本身中(因此您不需要去完整记录。)

    在第一种情况下,您有两种读取最佳情况,一种用于读取索引,另一种用于读取完整记录。

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

    如果您在不需要额外读取行的情况下满足完整的查询,则可以在索引中包含要存储的额外列以及包含索引的字段。

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

    如果您按顺序读取多个索引键(例如 SELECT ... FROM ... WHERE 键在 n1 和 n2 之间),则有一个特别大的优势,因为索引读取可能会彼此相邻存储并且可以可能只用一两个物理扇区读取;并且不需要查找其余记录提供了更多的杠杆作用。

    【讨论】:

    • 很好地解释了为什么它不适用于聚集索引
    【解决方案3】:

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

    Reference:

    包括(列 [ ,... n ] )

    指定非键列 添加到叶级 非聚集索引。非集群的 索引可以是唯一的或非唯一的。

    【讨论】:

      【解决方案4】:

      如果查询使用包含的列,则无需进行键查找。示例。

      select ssn, firstname from myusers where ssn='111-11-1111'
      

      合适的索引应该是这样的

      create index idx_user_ssn nonclustered on myusers(ssn) include(firstname)
      

      【讨论】:

        【解决方案5】:

        Include Index 的优点是避免了大小限制。

        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);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-02
          • 2020-11-05
          • 1970-01-01
          相关资源
          最近更新 更多