【问题标题】:Why SQL Server Tuning Advisor proposes to add PRIMARY KEY to included columns of index?为什么 SQL Server Tuning Advisor 建议将 PRIMARY KEY 添加到包含的索引列?
【发布时间】:2023-03-20 18:14:01
【问题描述】:

我已经多次看到这种情况,当我在 SQL Server 数据库引擎优化顾问中运行一些分析时,它建议我创建如下索引:

CREATE NONCLUSTERED INDEX [_index] ON [dbo].[SomeTable] 
(
    [Column1] ASC,
    [Column2] ASC,
    [Column3] ASC
)
INCLUDE ([PrimaryKeyColumn])

在包含的列列表中包含主键(聚集索引)列真的很重要吗?我一直认为它默认包含在原始行的链接中。我错了吗?

更新: 我认为同样重要的是要注意它提出了这样的查询索引,例如: SELECT [PrimaryKeyColumn] FROM [dbo].[SomeTable] WHERE ...[Conditions]... 它确实会影响性能和执行计划。 据我所知,索引并不包含真正的“聚集索引”,而只是一些指向行的链接。是这样吗?

【问题讨论】:

  • 主键和聚簇索引并不总是 1-1。您应该避免将两者混为一谈。
  • @Damien_The_Unbeliever 在这种情况下,PrimaryKeyColumn 在集群中。这就是我想在描述中指出的。如果我错过了什么,请告诉我。

标签: sql-server indexing database-tuning


【解决方案1】:

您可以创建带有或不带有 INCLUDE 的索引:SQL Server 将忽略它如果 PrimaryKeyCol 是聚集索引。也就是说,它不会存储两次聚集索引值

为了完整起见,我可能会更改聚集索引

编辑:

我通过 size 观察到 SQL Server 可以智能地处理此问题
这个不如Kalen Delaney's More About Nonclustered Index Keys科学

DROP TABLE IncludeTest;
GO
CREATE TABLE IncludeTest (
    BadClusteredKey uniqueidentifier DEFAULT NEWID() PRIMARY KEY,
    OtherCol AS CHECKSUM(BadClusteredKey) % 10000,
    Filler char(200) NOT NULL DEFAULT 'a and lots of spaces'
    );
GO

INSERT IncludeTest (Filler) VALUES (DEFAULT);
GO
INSERT IncludeTest (Filler) SELECT Filler FROM IncludeTest
GO 20
SELECT COUNT(*) FROM IncludeTest;

EXEC sp_spaceused 'IncludeTest', 'true'
GO -- 400680 KB, 1920 KB

CREATE INDEX IX_OtherCol1 ON IncludeTest (OtherCol);
GO
EXEC sp_spaceused 'IncludeTest', 'true'
GO -- 400680 KB, 29024 KB KB

DROP INDEX IncludeTest.IX_OtherCol1
GO
EXEC sp_spaceused 'IncludeTest', 'true'
GO -- 400680 KB, 1920 KB

CREATE INDEX IX_OtherCol2 ON IncludeTest (OtherCol) INCLUDE (BadClusteredKey);
EXEC sp_spaceused 'IncludeTest', 'true'
GO -- 400680 KB, 29024 KB

DROP INDEX IncludeTest.IX_OtherCol2
GO
EXEC sp_spaceused 'IncludeTest', 'true'
GO -- 400680 KB, 1920 KB

【讨论】:

  • +1 现在很高兴知道这一点。你有这方面的参考吗?
  • @Lieven Kalen Delaney: More About Nonclustered Index Keys。此外,如果 NCI 不是唯一的,则 CI 密钥将成为 NCI 密钥的一部分,而不仅仅是包含的列。
  • @Lieven:我只是在测试它,稍后会添加脚本
  • @MartinSmith:谢谢,我一直基于索引的大小
  • @gbn 感谢您提供如此好的脚本示例。当我将聚集索引列添加到包含的 SQL Server 更改了查询的执行计划时,它看起来仍然很奇怪,但目前我无法再重现它。可能是其他因素影响了变化。
【解决方案2】:

我认为 Tuning advisor 检测到您的查询,发现您在选择原因中有 PrimaryKeyColumn,并且在 where 原因中有 Column1、Column2 和 Column3。

调整顾问认为.... 如果您在索引中包含 PrimaryKeyColumn,则 SQL 不需要浪费开销来查找数据页(表数据页)中的 PrimaryKeyColumn 数据。 SQL 引擎将能够直接从索引中获取 PrimaryKeyColumn 值供您查询。它节省时间..

注意:索引有坏的一面(包括列)。 http://msdn.microsoft.com/en-us/library/ms190806.aspx 包含可能有助于您做出决定的有用信息。

【讨论】:

    猜你喜欢
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 2011-01-12
    • 1970-01-01
    相关资源
    最近更新 更多