【问题标题】:Would there ever be a good reason to replace a clustered index with a unique non-clustered index是否有充分的理由用唯一的非聚集索引替换聚集索引
【发布时间】:2014-10-22 16:19:02
【问题描述】:

我正在清理数据库,但由于流量过大而存在性能问题。读写。但繁忙的交通每年只有几天。

我怀疑一个问题是很多频繁使用的表没有聚集索引。但它们确实有一个主键和一个与之相关的唯一非聚集索引,该索引仅在主键上(不包含)。

这在任何时候都是一种有益的方法吗?

我的猜测是有人认为如果数据库不必插入聚集索引中的所有列会更快(我自己不会这样做,所以我不知道该方法背后的疯狂)。

我正在开始对这些表应用聚集索引的任务,但想在我走得太远之前调查更聪明的人,看看这样的策略是否会有所帮助?

我认为失去与聚集索引的连接会超过这可能带来的任何好处?

【问题讨论】:

  • 你是说支持主键的索引是非聚集的?因为那很不寻常。通常,主键也是聚集索引,这可能是最优的,也可能不是最优的,但这是另一回事。
  • 是的。有一个字段被指定为主键。在该字段(并且仅该字段)上定义了一个唯一的非聚集索引。它是表中唯一的索引。我知道这很奇怪。我以前从未见过。

标签: sql sql-server database-administration


【解决方案1】:

我很有信心说不,这从来都不是一种有益的方法。如果一个表只有非聚集索引,那么它就是一个堆表,除了批量插入操作之外,没有充分的理由拥有一个堆表。这不只是我在说,那是Microsoft's opinion as well

我维护了一个大仓库,在那里完全没有主键是个好主意(因为它的索引占用了大量空间而没有被使用),但只有一个唯一的聚集索引 @ 987654322@ 加上ID。但是你会注意到,不管是否有主键,它确实有一个聚集索引,因为没有一个只是一个坏主意。

【讨论】:

  • 好吧,除了你给出的正当理由之外,大量的插入内容很少,如果有的话,读取。
  • @Steve:我能想到的所有场景都涉及使用该表作为其他东西的暂存源,但你说得对,这不一定只是批量插入。例如,您可以有一个专门用于记录从不查询的事件的表,除非在一天结束时将它们复制到仓库。
  • 完全同意你的看法。
【解决方案2】:

没有。如果您有候选键,则将其用作聚集索引。唯一的非聚集索引可用于键查找并保证唯一性。聚集索引将用于此目的,此外还用于范围扫描和排序保证。

当繁忙的流量压缩为“几天”时,这表示时间序列,其中查询要求提供最近的范围:今天、最后一天、最后一天的总计和其他聚合周等。按时间组织表格使所有这些查询都可以工作,而不必扫描整个表格,端到端。

主键不必与聚集索引匹配。主键是一个逻辑概念,可用于对数据进行建模并在主/外键关系中强制引用完整性(严格来说,外键可以引用 任何 列,但大多数情况下它引用主键)。

聚集索引将定义物理布局,由围绕最频繁查询、存在的范围扫描类型和键大小权衡的实际考虑驱动。

添加聚集索引可能会改变一些访问模式,并可能引入新的死锁可能性,但坦率地说,这种可能性很小。通常是删除一个会增加死锁的聚集索引,而不是添加它。

最后,我不会太担心插入/更新成本。大多数应用程序具有压倒性的读写比,更快的读取使应用程序感觉更灵敏,更“活泼”。此外,具有可用索引的读取改进表现为 x100 倍的改进(小范围扫描与表端到端扫描),而写入降级表现为分数增加(例如写入时间增加 10-15%),通常在应用程序。

【讨论】:

    【解决方案3】:

    当您没有聚集索引但有主键时,插入会快得多,但仍然存在唯一性。因此,虽然标准堆需要查询来搜索每条记录以找到所需的记录,但具有非聚集主键的堆将在找到第一个结果后停止。虽然这仍然很慢,但总比没有快,如果您对 1 个查询执行 1M 插入操作,那么值得。

    日志表是一个很好的例子。

    【讨论】:

    • 我链接的来自 Microsoft 的文章有基准测试,显示堆表在几乎所有场景(插入、更新、删除)中都较慢,除了高并发插入。因此,您需要更加仔细地进行测试,因为堆表总能提供更好的插入性能绝对不是真的,这可能违反直觉(同样,显然不计算并行批量插入)。
    猜你喜欢
    • 2014-11-04
    • 2013-08-07
    • 2011-04-05
    • 2015-10-13
    • 2020-08-04
    • 2014-01-08
    • 2012-08-26
    • 2011-04-17
    相关资源
    最近更新 更多