一个索引还是两个?

pau*_*ulH 11 index sql-server sql-server-2008-r2 index-tuning

我在数据库的表上创建了以下索引:

CREATE INDEX [idx_index1]
on [table1]
(col1, col2, col3)
Run Code Online (Sandbox Code Playgroud)

服务器建议以下“缺失”索引:

CREATE INDEX [idx_index2]
on [table1]
(col1, col2)
INCLUDE (col3, col4, col5, col6....)
Run Code Online (Sandbox Code Playgroud)

在我看来,修改现有索引定义以包含建议的列而不是创建需要维护的新索引似乎是合乎逻辑的。在 col1 和 col2 上进行选择的查询可以像使用 index2 一样有效地使用 index1。我是正确的还是我可能遗漏了什么?

Tho*_*ger 12

于是进入了性能调优和索引策略的艺术......

修改现有索引定义以包含建议的列对我来说似乎合乎逻辑

我将引用您的报价并编写第三个索引定义:

create index [idx_index3]
on [table1] (col1, col2, col3)
include (col4, col5, col6....);
Run Code Online (Sandbox Code Playgroud)

那应该是CREATE INDEX与您引用的声明相对应的声明。

这很可能是一个谨慎的解决方案,但这取决于。当我说这取决于情况时,这里有几个例子。

如果您有一个主要由以下查询组成的常见工作负载:

select col1, col2, col3
from table1
where col1 = 1
and col2 = 2
and col3 = 3;
Run Code Online (Sandbox Code Playgroud)

那么你的idx_index1索引将是可靠的。完全狭窄,它是一个满足查询的索引,其中没有无关数据(不考虑聚集索引定义,如果有的话)。

但是,如果您的工作负载主要由以下查询组成:

select co11, col2, col3, col4, col5
from table1
where col1 = 1
and col2 = 2;
Run Code Online (Sandbox Code Playgroud)

然后idx_index2是明智的,因为它是所谓的覆盖索引,可以防止需要返回聚集索引的键查找(或返回堆的 RID 查找)。该非聚集索引定义将仅包含查询所需的所有数据。

根据您的建议,它将非常适合如下查询:

select co11, col2, col3, col4, col5
from table1
where col1 = 1
and col2 = 2
and col3 = 3;
Run Code Online (Sandbox Code Playgroud)

您的idx_index3建议是满足上述查询的搜索条件的覆盖索引。

我想说的是,在这样一个孤立的问题中,我们无法明确回答这个问题。这完全取决于常见和频繁的工作负载是什么。当然,您始终可以定义所有这三个索引来处理每个示例查询类型,但随后就会质疑保持这些索引更新所需的维护(想想:INSERT、UPDATE、DELETE)。这就是索引的开销。

您需要剖析和评估工作负载,并确定哪些优势最适合。如果第一个示例查询是迄今为止最常见的,每秒执行数十次,并且像第三个示例查询那样非常不频繁的查询,那么使用INCLUDE非键列。这一切都取决于您的工作量。

如果您了解谨慎的索引策略,并且了解您的常见工作负载,那么通过应用这两种策略,您将能够想出最好的方法。


Joh*_*som 7

您确实是正确的,并且已经发现为什么 DBA始终查看缺失的索引 DMV 等提出的“建议”很重要。

考虑到缺失索引 DMV 提供的建议是单独提出的,这意味着 SQL Server 决定推荐结构的索引将有益于查询,而不管其他索引结构可能已经存在。