非聚集索引将部分覆盖 select 查询

Nonclustered indexes will partially cover the select query

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

请查找我为 FACTORS table 创建的非聚集索引。

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 查询,我的索引 FACTORS_BKEY_PNO_IDX 会覆盖我的 select 查询。 (我的意思是这个索引会帮助我下面的 select 查询更快地检索记录,还是我需要创建另一个与 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

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

索引可以在两个主要方面提供帮助

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

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

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

但是,如果索引表明有太多的行,SQL 引擎通常会立即读取整个 table,就好像那里没有索引一样已经.

Brent Ozar 制作了一个非常好的视频,名为 How to think like an SQL Server engine - 如果您使用的是 dbo。我猜您正在使用 SQL 服务器。我强烈推荐观看它,因为我从中学到了很多关于索引等的知识,而且你似乎有很好的基础知识水平,也能学到很多东西。

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