【问题标题】:Better to use a Clustered index or a Non-Clustered index with included columns?最好使用包含列的聚集索引或非聚集索引?
【发布时间】:2010-01-22 19:23:25
【问题描述】:

当我查看特定查询的执行计划时,我发现 77% 的成本是在聚集索引搜索中。

我使用聚集索引这一事实是否意味着我不会看到由于我输出的列而导致的性能问题?

创建一个非集群版本并包含所有正在输出的列对我来说会更好吗?

更新: 聚集索引使用复合键。不确定这是否会有所不同。

【问题讨论】:

  • 这个信息太少了,无法给你一个好的推荐。你的桌子是什么样子的?有哪些领域?哪些字段被索引?您最常见的查询是什么样的??
  • 成本是相对的:您能给我们更多信息吗?
  • Hrrm,您还需要什么其他信息?占用 77% 成本的子树使用了大约 97% 的经过时间和大约 60% 的 CPU 时间。它最终返回接近 600,000 条记录。
  • 嗯,是查询计划的子树占了 77% 还是聚集索引 seek 本身占了 77%?您的查询返回 600,000 行;我想你担心需要多长时间(不管那个时间是多少)? 600,000 行是相当数量的数据。将其发送给客户端需要一段时间。您是否确认是执行时间有问题,还是传输时间有问题?当这不是问题时,您不会想浪费太多时间来改进查询。
  • 它是索引搜索本身。我如何确认它是执行时间而不是传输时间?

标签: sql sql-server


【解决方案1】:

在非聚集索引上使用包含列的原因是为了避免“书签查找”到聚集数据中。问题是,如果 SQL Server 理论上 可以使用特定的非聚集索引,但优化器估计会有“太多”书签查找,那么所述索引将被忽略。但是,如果所有选定的列都可以直接从索引中访问,则不需要书签查找。

在您的情况下,您通过“聚集索引搜索”访问数据的事实非常有希望。提高它的性能将非常困难。包含所有选定列的非聚集索引可能会稍微快一点,但这只是因为原始数据少了一点。 (但不要忘记增加插入/更新时间的成本。)

但是,你应该检查细节......

  • 如果您使用复合键并且搜索实际上只在键的开头,那么您可能就没那么幸运了。您可能会发现搜索仅缩小到 500,000 行,然后根据其他条件进行搜索。在这种情况下,尝试使用一些非聚集索引。
  • 聚集索引搜索本身可能没问题;但是,如果由于某些其他方面效率低下返回太多行而在您的查询中执行了 100,000 次,那么您不会通过提高聚集索引查找的性能获得太多收益。

最后,详细说明 davek 的评论:“成本是相对的”。仅仅因为集群是查询成本的 77% 并不意味着存在问题。可以编写一个简单的 1 表查询,该查询返回单行和 100% 的聚集索引查找成本。 (当然,作为唯一完成的“工作”,它将是 100% 的工作......而且 100% 的即时仍然是即时
所以:“别担心;要快乐!”

【讨论】:

  • 您对复合键的评论非常有趣。这个特定的索引是一个复合键。您能否详细说明“用非聚集索引进行实验”是什么意思?
  • 假设您的聚集索引在 (A, B, C) 上,但您的查询在 A 和 C 上进行过滤。然后聚集索引可以搜索,但不会以最佳效率使用(即只会在 A) 上寻找。 (A,C) 或 (C,A) 上的非聚集索引可能会更有效。如果过滤器返回的行数较少;那么太好了 - 一些书签查找,您的查询将非常有效地运行。但是,如果它返回许多行,则书签查找不再有效,并且索引将被忽略。所以尝试添加包含列。首先尝试哪些取决于您的其余查询。
【解决方案2】:

您已经有一个目标,因此收益可能微乎其微。

你可以试试。选项:

  • 第二个非聚集索引,保持原始
  • 将聚集索引移动到另一列

还有其他好的集群候选者吗?注意,你总是需要一个唯一的聚集索引(因为uniquifiers + here SO + here)。当然,请问你的PK是什么?

【讨论】:

  • 我有一个组合PK。组成 PK 的两列是正在使用的聚集索引中的两列。
【解决方案3】:

这取决于您所谈论的列数,如果是一对,则非聚集索引的性能会更好,如果您选择大多数列,则聚集索引会更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    • 2020-08-04
    • 2013-08-07
    • 2011-06-02
    相关资源
    最近更新 更多