756

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

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

例如:

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)
4

5 回答 5

370

我同意凯德鲁斯的观点。

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

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

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

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

州、县、邮编。

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

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

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

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

顺便说一句,我们可以利用这样一个事实,即使用多列索引,第一个索引列始终可用于搜索,当您仅按“状态”搜索时,它是有效的,但不如“状态”上的单列索引高效'

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

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

于 2008-10-07T16:10:57.883 回答
86

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

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

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

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

于 2008-10-07T15:41:55.880 回答
51

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

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

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

于 2008-10-07T15:46:51.520 回答
17

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

于 2008-10-07T19:19:31.153 回答
12

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

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

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

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

于 2008-10-07T15:46:19.897 回答