【问题标题】:Multiple Indexes vs Multi-Column Indexes多索引与多列索引
【发布时间】:2010-09-15 19:09:01
【问题描述】:

我刚刚在 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)

【问题讨论】:

    标签: sql-server database indexing


    【解决方案1】:

    我同意Cade Roux

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

    需要注意的是,聚集索引应该有一个唯一键(我推荐的标识列)作为第一列。 基本上它可以帮助您在索引末尾插入数据,并且不会导致大量磁盘 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)“然后,在所有这三个搜索中都将使用包含州、县、邮编的索引。”是错误的,并且与“第一列可用”相矛盾。索引中的第二个 & 子列不可用于搜索。
    • 在表中添加大数据后,取数据速度慢。如何解决这个问题任何帮助。 (使用 PostgreSQL 数据库)
    【解决方案2】:

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

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

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

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

    【讨论】:

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

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

    【讨论】:

    • +1 链接很好地解释了如何使用(普通)索引,与问题相关。
    【解决方案4】:

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

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

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

    【讨论】:

    • 这是正确的。但是,将这些列作为单个索引每个仍然会显着加快速度。通常,列中的一个值会大大减少结果集,以至于在没有索引的情况下查找其余值并不重要,优化器擅长选择这个值。
    【解决方案5】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2011-11-07
      • 1970-01-01
      • 2018-07-27
      • 1970-01-01
      • 2020-05-06
      • 1970-01-01
      • 2019-03-22
      • 1970-01-01
      相关资源
      最近更新 更多