Sql server SQL Server 2014索引优化:在索引中包含主键有什么好处?

Sql server SQL Server 2014索引优化:在索引中包含主键有什么好处?,sql-server,performance,Sql Server,Performance,运行查询后,SQL Server 2014实际查询计划显示缺少的索引,如下所示: CREATE NONCLUSTERED INDEX IX_1 ON Table1 (Column1) INCLUDE (PK_Column,SomeOtherColumn) 缺少的索引建议在索引中包含主键列。该表是带有PK_列的聚集索引 我很困惑,似乎我没有正确理解聚集索引主键的概念 我的假设是:当一个表有聚集的PK时,所有非聚集索引都指向PK值。我说得对吗?如果是,为什么缺少索引的查询计划要求我在索引中包含

运行查询后,SQL Server 2014实际查询计划显示缺少的索引,如下所示:

 CREATE NONCLUSTERED INDEX IX_1 ON Table1 (Column1) INCLUDE
 (PK_Column,SomeOtherColumn)
缺少的索引建议在索引中包含主键列。该表是带有PK_列的聚集索引

我很困惑,似乎我没有正确理解聚集索引主键的概念


我的假设是:当一个表有聚集的PK时,所有非聚集索引都指向PK值。我说得对吗?如果是,为什么缺少索引的查询计划要求我在索引中包含PK列?

摘要:
建议的索引无效,但没有任何区别。有关详细信息,请参阅下面的测试部分

在研究了一段时间后,发现下面的语句有力地解释了缺失的索引特征

它们只查看单个查询,或单个查询中的单个操作。它们不考虑已经存在的内容或其他查询模式

你仍然需要一个善于思考的人来分析整体索引策略,并确保你的索引结构是高效和内聚的

所以说到你的问题,这个建议的指数可能是有效的,但不应该被认为是理所当然的。建议的索引对于SQL Server执行的特定查询非常有用,以降低成本

这是建议的索引

 CREATE NONCLUSTERED INDEX IX_1 ON Table1 (Column1) 
        INCLUDE (PK_Column, SomeOtherColumn)
假设您有一个如下所示的查询

select pk_column, someothercolumn 
from table 
where column1 = 'somevalue'
SQL Server也会尝试扫描窄索引(如果可用),因此在本例中,建议的索引将非常有用

此外,如果您有如下索引,您没有共享表的架构

create index nci_test on table(column1)
以下形式的查询将再次建议与问题中所述相同的索引

select pk_column, someothercolumn 
from table 
where column1 = 'somevalue'
更新:
我有以下模式的订单表

[orderid] [int] NOT NULL Primary key,
[custid] [char](11) NOT NULL,
[empid] [int] NOT NULL,
[shipperid] [varchar](5) NOT NULL,
[orderdate] [date] NOT NULL,
[filler] [char](160) NOT NULL
现在我又创建了一个以下结构的索引

create index onlyempid on orderstest(empid)
现在,当我有一个以下形式的查询

select empid,orderid,orderdate --6.3 units
from orderstest 
where empid=5
索引顾问将建议以下缺少的索引

CREATE NONCLUSTERED INDEX empidalongwithorderiddate
ON [dbo].[orderstest] ([empid])
INCLUDE ([orderid],[orderdate])--you can drop orderid too ,it doesnt make any difference
如果您可以看到orderid也包含在上述建议中

现在让我们创建它并观察这两种结构

---根水平-------

仅适用于索引MPID..

对于索引empidLongWithOrderIDDate

----叶面-------

仅适用于索引MPID..

对于索引empidLongWithOrderIDDate

正如您所看到的,按照建议创建没有任何区别,即使它是无效的


我假设这个建议是由Index advisor根据运行的查询提出的,并且是专门针对该查询的,它不知道涉及的其他索引,我不知道您的模式,也不知道您的查询。只是猜测而已

如果这个理论不正确,请纠正我

非聚集索引指向PK值是正确的。假设您有一个大型数据库(例如千兆字节的文件)存储在普通的平板硬盘上。假设磁盘是碎片化的,并且PK_索引保存在远离Table1索引的物理位置

假设您的查询还需要计算Column1和PK_列。查询执行读取Column1值,然后是PK_值,然后是Column1值,然后是PK_值

硬盘驱动器盘片正在从一个物理位置旋转到另一个物理位置,这可能需要时间


在一个索引中包含所有需要的内容更有效,因为这意味着按顺序读取一个文件

我认为这个建议是多余的(通常,缺少的索引建议需要仔细检查,以确定哪些建议是真正的好主意,因为优化器将建议所有内容和厨房水槽)。您可以尝试使用INCLUDE(SomeOtherColumn)创建索引,看看查询是否使用它,提示是否消失,这将是一个非常可靠的确认。您能否显示所涉及的表的查询计划和模式?您的理解是正确的-任何非聚集索引的叶级都包含该索引本身的列、任何包含的列和聚集键列。问题实际上是tuning advisor:这是一个软件,已知它建议进行不必要的、完全多余的更改。不要盲目地使用这些建议!模式与查询中的内容一致。您是否认为IX_1对您的查询实际有效?根据另一条评论,我认为PK_列不应该包括在内,它会增加存储开销,而不会带来任何好处。你同意吗?是的,对于我的答案中的查询类型,建议的索引是有效的,但仅限于此查询,现在我理解了你的答案。包含PK_列对您的第一次查询有何好处?索引已经有PK数据,为什么我们需要再次包含它?建议的索引使用column1作为键列,优化器将选择一个适合扫描窄索引而不是整个聚集索引的计划,但是如何包含(PK_列)帮助?PK_列已经包含在任何非聚集索引中,还是我的概念错了?