有什么理由同时拥有一个包含列的索引和一个不包含列的索引?

Lit*_*ium 7 index sql-server nonclustered-index

我正在查看在过去几年中(在许多不同的开发人员的领导下)取得重大发展的数据库上的一些运行缓慢的查询。
最常用的表之一有几个索引,它们具有相同的索引列,但其中一个包含列,另一个不包含。

例如:
一个索引:

 CREATE NONCLUSTERED INDEX [IDX_tblTable_IndexedColumnId_Inc] ON [dbo].[tblTable]
 (
[IndexedColumnId] ASC
 )
Run Code Online (Sandbox Code Playgroud)

然后另一个:

CREATE NONCLUSTERED INDEX [IDX_tblTable_IndexedColumnId_Inc] ON [dbo].[tblTable]
(
[IndexedColumnId] ASC
)
INCLUDE (   [Field1Id],
[Field2],
[Field3],
[Field4],
[Field5],
[Field6]) 
Run Code Online (Sandbox Code Playgroud)

我认为这只是一个疏忽,只是使用磁盘空间和额外的开销来获得没有包含列的索引(已知需要包含列)。

在同一列上有两个索引有什么好处,一个包含列,另一个没有?

Eri*_*ing 9

稍微扩展一下每个人最喜欢的 n 维模拟评论,两者兼而有之可能会有一些好处。

这是一个小(但不充分)的演示。

必要:

USE StackOverflow;
SET NOCOUNT ON; 

CREATE TABLE dbo.IndexCrap
(
    Id INT IDENTITY PRIMARY KEY CLUSTERED,
    Whatever DATETIME,
    Nonsense VARCHAR(50),
    Etc UNIQUEIDENTIFIER,
    SoForth BIT
);

INSERT dbo.IndexCrap WITH (TABLOCK)
        (Whatever, Nonsense, Etc, SoForth )
SELECT TOP 1000 DATEADD(DAY, x.n, GETDATE()),
                REPLICATE('A', x.n % 50),
                NEWID(),
                CASE WHEN x.n % 15 = 0 THEN 1 ELSE 0 END
FROM (SELECT ROW_NUMBER() OVER (ORDER BY @@ROWCOUNT) AS n
        FROM sys.messages AS m ) AS x;
Run Code Online (Sandbox Code Playgroud)

指标:

CREATE INDEX ix_tinydancer ON dbo.IndexCrap (Whatever);

CREATE INDEX ix_largemarge ON dbo.IndexCrap (Whatever) INCLUDE (Nonsense, Etc, SoForth);
Run Code Online (Sandbox Code Playgroud)

所以就像你的问题一样,在一列的索引上,同一列上的一个索引有一些包含。

查询:

SELECT COUNT(*)
FROM dbo.IndexCrap AS ic;

SELECT ic.Nonsense, ic.Etc, ic.SoForth
FROM dbo.IndexCrap AS ic
WHERE ic.Whatever >= DATEADD(DAY, 500, GETDATE());
Run Code Online (Sandbox Code Playgroud)

执行计划:

对于COUNT(*)查询,优化器选择我们最小的单列索引而不是更宽的非聚集索引和稍宽的聚集索引,因为它没有被过滤,我们只需要一个行数。

坚果

对于更广泛的查询,优化器选择覆盖索引,因此它不必 a) 扫描聚集索引或 b) 访问较窄的索引并将键查找返回到聚集索引。

坚果

当然,您可能不知道系统上运行的每个查询。这就是为什么我工作的公司写sp_BlitzIndex了一个免费的工具来分析你的索引

如果我们运行EXEC master.dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow', @Mode = 4;,这里有一些我们感兴趣的结果:

坚果

我添加到的两个索引IndexCrap(不包括 PK/CX)被标记为具有重复的键列。它还给出了它们的定义、用法、大小以及更多未在屏幕截图中显示的内容。

使用计数器并不完美。如果您添加或删除索引,它们将重置,在某些版本的 SQL Server 中,如果您重建索引,它们将重置,当然,如果您重新启动 SQL Server,它们将重置。

希望这可以帮助!


归档时间:

查看次数:

1247 次

最近记录:

8 年,7 月 前