一两个索引?


11

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

CREATE INDEX [idx_index1]
on [table1]
(col1, col2, col3)

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

CREATE INDEX [idx_index2]
on [table1]
(col1, col2)
INCLUDE (col3, col4, col5, col6....)

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

Answers:


12

因此,进入了性能调整和索引策略的艺术领域……

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

我将以您的报价为基础并编写第三个索引定义:

create index [idx_index3]
on [table1] (col1, col2, col3)
include (col4, col5, col6....);

那应该是CREATE INDEX与您引用的语句相对应的语句。

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

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

select col1, col2, col3
from table1
where col1 = 1
and col2 = 2
and col3 = 3;

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

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

select co11, col2, col3, col4, col5
from table1
where col1 = 1
and col2 = 2;

idx_index2将是明智的,因为这就是所谓的覆盖索引,可避免需要对聚集索引(或对堆的RID查找)进行键查找。该非聚集索引定义将仅包含查询所需的所有数据。

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

select co11, col2, col3, col4, col5
from table1
where col1 = 1
and col2 = 2
and col3 = 3;

您的idx_index3推荐将是满足上述查询搜索条件的覆盖索引。

我要说的是一个孤立的问题,我们无法确切地回答。这完全取决于常见和频繁的工作量。当然,您总是可以定义所有这三个索引来处理每种示例查询类型,但是随之而来的是保持这些索引更新所需的维护(例如:INSERT,UPDATE,DELETE)。那就是索引的开销。

您需要剖析和评估工作负载,并确定在哪些方面优势最大。如果第一个示例查询是目前为止最常见的一次每秒执行数十次,并且不像第三个示例查询那样非常不频繁地进行查询,则使用INCLUDE非关键列。这完全取决于您的工作量。

如果您了解审慎的索引编制策略,并且了解常见的工作量,则通过同时使用这两种方法,您将能够提出最佳的选择方法。


我将不得不消化一会儿,但这似乎是一个很好的答案。我认为您定义的'index3'具有col3作为等于列和包含列是错字。
paulH,2013年

是的:-)不错。我已经将其删除。
Thomas Stringer

更不用说如果表仅具有1-6列,则索引1和2并包含3-5是非常愚蠢的。
肯尼斯·费舍尔

1
@KennethFisher-为什么那会很傻?如果您的数据库结构和工作量可以保证,这似乎是一件足够合理的事情。例如,如果您有一个查询根据第1列和第2列的值选择第1-5列,并且第6列可能是您不想膨胀索引的nvarchar(max)列。
paulH,2013年

1
@paulH这可能只是我的意见,但是此时您已在include中添加了足够多的列,索引中的表中有90%以上的列已被索引you肿,以至于多余的读入表中本身并不那么重要。现在肯定有例外..如果cols 1-5都是int的,而col6是varchar(max),那么我可以这样做。但总的来说,我会非常仔细地研究这些内容。
肯尼斯·费舍尔

7

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

考虑到缺少索引DMV所提供的建议是孤立提出的,这意味着SQL Server决定,推荐结构的索引将使查询受益,而与其他任何索引结构无关。


3

多一点,关于托马斯回答的含义之一:

他说:

当然,您总是可以定义所有这三个索引来处理每种示例查询类型,但是随之而来的是保持这些索引更新所需的维护(例如:INSERT,UPDATE,DELETE)。那就是索引的开销。

因此,另一个大问题变成了:表多久更新一次?

首先考虑一个不断更新的表的示例,例如ORDERS反映网站消费者活动的零售表...在那里,您要认真考虑拥有多个索引,因为它们增加了不断更新的工作量,因此不断影响数据库的性能。

在另一方面,考虑到只更新网站安装的一部分表-表更新ONCE对于大多数的价值观,以及很少的附加价值-在那里,更新速度变慢是几乎考虑。多个索引可能会减慢数据库索引的重建和重组速度,但是只要它们足够快,就可以免费使用:如果多个索引加快了读取速度,那就去吧。

一个中间情况可能是一个表,该表通常仅在一整批过程中在一夜之间进行更新。在那里,来自多个索引的更新速度降低不会影响白天的性能 -它们只会影响(1)运行夜间批维护的时间,(2)任何并发进程的性能以及(3)花费的时间。数据库维护任务,例如索引重组。因此,只要在这三个领域中的进程对您来说运行得足够快,就可以创建加速查询的索引。

嗯...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.