ChatGPT解决这个技术问题 Extra ChatGPT

多索引与多列索引

跨多列创建一个索引与创建多个索引(每列一个索引)有什么区别?

有什么理由为什么应该使用一个而不是另一个?

例如:

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)

A
Arash.Zandi

我同意Cade Roux

这篇文章应该让你走上正轨:

SQL Server 2005/2008 中的索引 – 最佳实践,第 1 部分

SQL Server 2005/2008 中的索引 – 第 2 部分 – 内部

需要注意的一点是,聚集索引应该有一个唯一键(我推荐的标识列)作为第一列。基本上,它可以帮助您在索引末尾插入数据,并且不会导致大量磁盘 IO 和页面拆分。

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

例如,假设您在三列上搜索表格

州、县、邮编。

您有时仅按州搜索。

您有时会按州和县进行搜索。

您经常按州、县、邮编搜索。

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

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

然后,您可以仅在 Zip 上创建将在此实例中使用的索引。

顺便说一下We can take advantage of the fact that with Multi-Column indexing the first index column is always usable for searching,当您仅按“状态”搜索时,它是有效的,但不如“状态”上的单列索引高效

我想您正在寻找的答案是它取决于您经常使用的查询的 where 子句以及您的 group by。

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


那么除了为每列单独的索引之外,最好的办法是为州、县和邮编定义一个索引吗?
@jball 我在这里错过了什么吗?看起来这篇文章主要是关于 SQL Server 版本限制之间的差异。文章可以移动吗?
@Ian 自从我在 4 年前整理出原始链接以来,在 3 年内似乎确实丢失了一些东西。我可以告诉你,该博客文章的标题与 evilhomer 链接的标题正确,但看起来该系列中的后续博客不再容易从第一篇文章中找到。您将不得不在 Kimberly 的博客存档中查看是否可以找到该系列中的其他人。
1)“基本上[以 IDENTITY 列为第一的聚集索引]有助于您在索引末尾插入数据”是正确的。 “并且不会导致大量磁盘 IO 和页面拆分”在多用户系统中是完全错误的。事实上,它保证多用户系统中的高争用(低并发)。 2)聚集索引应该是一个关系键,即。 不是 IDENTITY, GUID, etc。 3)“然后,在所有这三个搜索中都将使用包含州、县、邮编的索引。”是错误的,并且与“第一列可用”相矛盾。第二个&索引中的 subs cols 不可用于搜索。
C
Cade Roux

是的。我建议您查看 Kimberly Tripp's articles on indexing

如果一个索引是“覆盖”的,那么除了索引之外不需要使用任何东西。在 SQL Server 2005 中,您还可以向索引中添加不属于键的附加列,从而消除对行其余部分的访问。

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

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


Kimberly Tripp 知道她在说什么。我正在谈论她的谈话,她对这些东西了如指掌。很好的建议。
@CadeRoux如果大多数时候我的where子句在'&'关系中有2列,那么最好对它们进行多列索引还是对它们都有单列索引
@RachitGupta 一个包含两列的索引
M
MobyDX

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

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

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


这是对的。但是,将这些列作为单个索引仍然会显着加快速度。通常,列中的一个值会大大减少结果集,以至于在没有索引的情况下查找其余值并不重要,并且优化器擅长选择该值。
为什么最多只使用一列?当它查找 column1 时,它不能也使用 column2 的索引吗?
C
ConcernedOfTunbridgeWells

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


+1 链接很好地解释了如何使用(普通)索引,与问题相关。
B
Bob Probst

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

通过在索引中放置多个列,优化器只需在列不在索引中时直接访问表。我在数据仓库中经常使用这些。缺点是这样做会花费大量开销,尤其是在数据非常不稳定的情况下。

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

您应该问自己为什么要索引列以及如何使用它们。运行一些查询计划并查看它们何时被访问。索引调优既是本能,也是科学。