我在数据库中的表上创建了以下索引:
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。我是对的还是我可能遗漏了什么?
因此进入了性能调整和索引策略的艺术......
我要引用你的话并编写第三个索引定义:
那应该是
CREATE INDEX
与您引用的声明相对应的声明。这很可能是一个谨慎的解决方案,但要视情况而定。当我说这取决于时,这里有几个例子。
如果您有一个主要由如下查询组成的常见工作负载:
那么您的
idx_index1
索引将是可靠的。非常窄,它是一个满足查询的索引,其中没有多余的数据(不考虑聚簇索引定义,如果有的话)。但是,如果您的工作负载主要由如下查询组成:
然后
idx_index2
是明智的,因为它是所谓的覆盖索引,防止需要将键查找回聚簇索引(或 RID 查找回堆)。该非聚集索引定义将仅包含查询所需的所有数据。根据您的建议,它将非常适合如下查询:
您的
idx_index3
建议是满足上述查询的搜索条件的覆盖索引。我想说的是,在这样一个孤立的问题中,我们无法明确回答。这完全取决于常见和频繁的工作负载是什么。当然,您始终可以定义所有这三个索引来处理每个示例查询类型,但随后会质疑保持这些索引更新所需的维护(想想:INSERT、UPDATE、DELETE)。那是索引的开销。
您需要剖析和评估工作量,并确定最佳优势所在。如果第一个示例查询是最常见的,每秒执行几十次,并且有一个非常不频繁的查询,如第三个示例查询,那么用
INCLUDE
非键列。这完全取决于您的工作量。如果您了解审慎的索引策略,并且了解您的常见工作负载,那么通过应用这两者,您将能够想出最好的方法。
您确实是正确的,并且已经发现为什么 DBA始终审查缺失索引 DMV 等提出的“建议”很重要。
考虑到缺失索引 DMV 提供的建议是孤立提出的,这意味着 SQL Server 决定推荐结构的索引将有利于查询,而不管其他索引结构可能已经存在。
再多说一点,关于托马斯回答的含义之一:
他说:
那么,另一个大问题就变成了:表多久更新一次?
首先考虑一个不断更新的表的例子,例如,
ORDERS
反映网站消费者活动的零售表......在那里,你要认真对待拥有多个索引,因为它们增加了通过不断更新完成的工作,因此不断影响数据库的性能。另一方面,考虑一个仅作为网站设置的一部分更新的表——该表针对大多数值更新一次,并且不经常添加值——在那里,更新速度减慢几乎不是一个考虑因素。多个索引可能会减慢数据库索引重建和重组的速度,但只要它们足够快,请放心:如果多个索引可以加快读取速度,那就去做吧。
中间情况可以是通常只在一夜之间以批处理过程更新的表。在那里,来自多个索引的更新减速不会影响白天的性能——它们只会影响 (1) 运行夜间批处理维护所花费的时间,(2) 任何并发进程的性能,以及 (3)数据库维护任务,如索引重组。因此,只要这 3 个领域中的进程对您来说运行得足够快……创建可加快查询速度的索引。
哈特...