多个索引与多列索引


645

我一直在向SQL Server 2005中的表添加索引,这让我开始思考。创建1个索引和定义多个列而不是要索引的每列有1个索引之间有什么区别?

有某些原因为什么要使用另一种方法?

例如

Create NonClustered Index IX_IndexName On TableName
(Column1 Asc, Column2 Asc, Column3 Asc)

Create NonClustered Index IX_IndexName1 On TableName
(Column1 Asc)

Create NonClustered Index IX_IndexName2 On TableName
(Column2 Asc)

Create NonClustered Index IX_IndexName3 On TableName
(Column3 Asc)

Answers:


319

我同意凯德·鲁Cade Roux)的观点

本文应该使您走上正确的道路:

需要注意的一件事是,聚集索引应该在第一列中具有唯一键(我推荐身份列)。基本上,它可以帮助您在索引末尾插入数据,而不会引起大量磁盘IO和页面拆分。

其次,如果您要在数据上创建其他索引,并且它们被巧妙地构造,它们将被重用。

例如,假设您在三列中搜索一个表

州,县,邮编。

  • 您有时仅按州搜索。
  • 您有时会按州和县进行搜索。
  • 您经常按州,县,邮政编码搜索。

然后是带有州,县,邮政编码的索引。将在所有这三个搜索中使用。

如果您仅通过zip进行大量搜索,则上述索引将不会被使用(无论如何,SQL Server都不会使用),因为zip是该索引的第三部分,并且查询优化程序不会认为该索引有帮助。

然后,您可以单独在Zip上创建一个索引,该索引将在此实例中使用。

顺便说一下,我们可以利用以下事实:使用多列索引时,第一个索引列始终可用于搜索,而仅按“状态” 搜索时,它是有效的,但不如“状态”中的单列索引有效'

我猜您正在寻找的答案是,这取决于您常用查询的where子句以及group by的。

这篇文章会有所帮助。:-)


2
那么,除了为每列设置单独的索引之外,最好的办法是为州,县和邮政编码定义一个索引吗?
Maxim Zaslavsky 2010年

12
@jball我在这里想念什么吗?看起来这篇文章主要是关于SQL Server版本限制之间的差异。文章可以搬走吗?
Ian R. O'Brien 2013年

@Ian的确看起来像在我四年前从现在开始整理原始链接以来的三年中,已经丢失了一些东西。我可以告诉您,该博客文章的标题正确,与evilhomer所链接的一样,但是看起来该系列的后续博客不再容易从该第一篇文章中找到。您将不得不浏览Kimberly的博客档案,以查看是否可以打开该系列的其他文章。
jball

1
1)“基本上[以IDENTITY列为首的聚簇索引]可帮助您在索引末尾插入数据”是正确的。在多用户系统中,“并且不会引起大量磁盘IO和页面拆分”完全是错误的。事实是,它保证了多用户系统中的高竞争(低并发)。2)聚簇索引应该是一个关系键,即。不是一个IDENTITY, GUID, etc。3)“然后将在所有这三个搜索中使用带有州,县,邮政编码的索引。” 是错误的,并且与“第一列可用”相矛盾。索引中的第二和第二列不可用于搜索。
PerformanceDBA

82

是。我建议您查看Kimberly Tripp的有关索引的文章

如果索引正在“覆盖”,则除了索引外,无需使用其他任何内容。在SQL Server 2005中,您还可以将其他列添加到索引中,这些列不属于键,因此可以避免跳至行的其余部分。

具有多个索引,每个索引都在一个列上可能意味着只使用了一个索引-您将必须参考执行计划以查看不同索引方案提供的作用。

您还可以使用调整向导来帮助确定哪些索引将使给定查询或工作负载表现最佳。


7
金伯利·特里普(Kimberly Tripp)知道她在说什么。我在和她聊天,她从里到外都知道这些东西。很好的建议。
evilhomer

@CadeRoux如果大多数情况下,我的where子句在'&'关系中有2列,则最好在它们上有多列索引,或者在它们两者上都具有单列索引
这是个陷阱,发生

2
@RachitGupta包含两个列的索引
Cade Roux

41

多列索引可用于引用所有列的查询:

SELECT *
FROM TableName
WHERE Column1=1 AND Column2=2 AND Column3=3

可以使用多列索引直接查找。另一方面,最多可以使用一个单列索引(它必须查找所有具有Column1 = 1的记录,然后检查每个记录中的Column2和Column3)。


24
这是对的。但是,将这些列作为单个索引仍然可以大大加快工作速度。通常,这些列中的一个值会减少结果集,以至于没有索引的情况下查找其余值都没有关系,并且优化程序擅长选择此值。
TToni

17

似乎缺少的一项是恒星变换。 索引交集运算符通过在事实表上完成任何I / O之前计算每个谓词命中的行集来解析谓词。在星型模式中,您将为每个单独的维度键编制索引,并且查询优化器可以解析通过索引交集计算选择的行。各个列上的索引为此提供了最大的灵活性。


+1为如何使用(普通)索引提供了与问题相关的链接式良好解释。
RobM 2011年

8

如果您的查询经常使用相对静态的一组列,则创建一个包含所有列的覆盖索引将大大提高性能。

通过在索引中放置多个列,优化器将仅在索引中没有列的情况下直接访问表。我在数据仓库中经常使用这些。不利之处在于,这样做可能会花费大量开销,尤其是在数据非常不稳定的情况下。

在单列上创建索引对于OLTP系统中常见的查找操作很有用。

您应该问自己为什么要索引这些列以及如何使用它们。运行一些查询计划,看看何时访问它们。索引调整与科学一样具有本能。

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.