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

问题描述

我在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查询,我的索引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_VALUE

解决方法

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

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

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

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

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

但是,如果索引指示为此目的有太多行,那么SQL引擎通常会一次读取整个表,就像那里没有索引一样。

如果您使用的是dbo,Brent Ozar会在名为How to think like an SQL Server engine的视频上做得非常好。我猜您正在使用SQL Server。我强烈建议您观看它,因为我从它中学到了很多有关索引等的知识,并且您似乎掌握了不错的基础知识,也能收获很多。

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...