【问题标题】:Nonclustered indexes will partially cover the select query非聚集索引将部分覆盖选择查询
【发布时间】:2021-02-23 14:40:10
【问题描述】:

我在我的 SQL 数据库服务器中使用 Include 关键字创建了一个非聚集索引。

请找到我为FACTORS 表创建的非聚集索引。

CREATE NONCLUSTERED INDEX [FACTORS_BKEY_PNO_IDX] ON [dbo].[FACTORS]
(
                [BATCH_KEY] ASC,
                [PART_NO] ASC
)
INCLUDE([FACTOR_NAME],[FACTOR_VALUE],[FACTOR_NAME_ETL],[INDUSTRY],[PROGRAM_ID],[PROGRAM_NAME]) WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
GO

如果我有一个像下面这样的 SELECT 查询,我的 indcxes FACTORS_BKEY_PNO_IDX 将覆盖我的选择查询。 (我的意思是这个索引将帮助我下面的选择查询更快地检索记录,还是我需要创建另一个与INCLUDE 字段完全匹配的索引)。

select 
BATCH_KEY , 
FACTOR_NAME , 
FACTOR_VALUE , 
INDUSTRY  
PART_NO , 
CREATED_TS , 
FACTOR_NAME_ETL , 
PROGRAM_ID , 
PROGRAM_NAME 
from 
FACTORS  
where BATCH_KEY and  PART_NO
order by 
PART_NO, FACTOR_NAME, FACTOR_VALUE

【问题讨论】:

    标签: sql indexing non-clustered-index


    【解决方案1】:

    由于非聚集索引不包括 SELECT 查询中的所有字段(例如,它没有 Industry),因此它不是覆盖索引。不幸的是,它需要从其他地方获取额外的数据,例如,通过返回原始表。

    索引可以通过两种主要方式提供帮助

    • 一个覆盖索引,其中包含查询所需的所有列 - 它可以减少要读取的数据量
    • 对数据进行预排序,以便进行索引查找

    最快的是当这两种情况都发生时,例如,它被适当地排序并且它是一个覆盖索引。在您的示例中,索引的主要字段看起来是合适的,但它不是覆盖索引。

    即使它不是覆盖索引,预排序仍然可以提供帮助,例如,它使用索引来确定要返回表中的哪些行以从中获取其余数据。它使用索引很像你在书中的索引 - 例如,你使用索引来查找书中的相关页面,然后去阅读每一页以获得你需要的信息。在这些情况下,较小的索引(例如,仅在 batch_key 和 part_no 上,没有其他字段)将以与您拥有的更广泛的索引相同的方式起作用。实际上,较小的索引略微会更好,因为它要读取的数据更少(2 列 vs 8 列):因为无论如何它都必须返回表才能获取数据;它也可以从那里获取其他列。

    但是,如果索引表明存在太多行,SQL 引擎通常会立即读取整个表,就好像那里还没有索引一样。

    Brent Ozar 在这方面做了一个非常棒的视频,名为 How to think like an SQL Server engine - 假设您使用的是 dbo。我猜你正在使用 SQL Server。我强烈建议您观看它,因为我从中学到了很多关于索引等的知识,而且您似乎拥有良好的基础知识水平也能收获很多。

    (PS - 我猜where BATCH_KEY and PART_NO 只是一个错字)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-09
      • 2015-03-18
      • 2018-08-04
      • 1970-01-01
      相关资源
      最近更新 更多