【问题标题】:Is it necessary to consider dropping the existing index because it is a prefix of the recommended index是否有必要考虑删除现有索引,因为它是推荐索引的前缀
【发布时间】:2011-10-28 02:31:02
【问题描述】:

Oracle SQL Developer v3 的 SQL Tuning Advisor 为我的查询提出以下建议:

考虑运行 Access Advisor 以改进物理架构 设计 或创建推荐的索引。 如果您选择创建 推荐索引,考虑删除索引SCHEMANAME”。“INDEXNAME”(在“COLUMN1”上)因为它是 推荐索引。

create index SCHEMANAME.NEW_INDEXNAME on SCHEMANAME.TABLENAME("COLUMN1","COLUMN2");

用粗体提出建议有什么害处吗?问题是它建议删除的现有索引被其他程序使用。我不认为 idex 会相互“伤害”,将两个索引与它们将占用的磁盘空间分开并且插入/更新时性能下降微不足道有什么缺点吗?

【问题讨论】:

    标签: sql performance oracle query-optimization


    【解决方案1】:

    因此,假设 OLD INDEX 在 [Column1] 上并且 RECOMMENDED INDEX 在 [Column1][Column2] 上,推荐的索引也可以用于现有查询。

    简而言之:删除 OLD INDEX 将如您所说提高插入/更新性能,并且也不会降低搜索能力 对使用 OLD INDEX 的查询进行过度扫描。推荐索引 仍然允许搜索 [Column1] 值以及 [Column1][Column2] 值。

    因此,除了更新/插入的性能下降和额外的存储开销之外没有任何危害,但维护这两个索引也没有收获

    【讨论】:

    • +1 但也许您还可以添加额外存储空间的缺点?
    • 准确!旧索引在 column1 上。好吧,如果删除它不会损害 column1 上的过滤,那么为什么我们不总是为我们查询的所有列创建一个大的胖索引呢?
    • @tsar 数据索引在不同的数据结构(SQL Server 中的 B-tree,其他 RDBMS 中不确定)中创建数据的副本。如果是非聚集索引,它将仅复制那些字段(在本例中为 Column1/Column2),然后引用以在整个表中查找该记录的其余数据。聚集索引将整个数据集存储在附加数据结构中。这意味着 大量 的数据开销,以及在插入/更新时平衡数据结构的大量处理。
    • 谢谢大家,在这里找到了我评论的答案:stackoverflow.com/questions/179085
    • 顺便说一句,在 [Column1][Column2] 上有一个索引将强制任何排序!只有一个 ORDER BY 语句强制排序,其他任何事情都是巧合,并且可能在任何未来的 Oracle 版本中发生变化!
    【解决方案2】:

    实际上,当您将索引放在单个列上时,性能可能会下降。

    假设您使用WHERE [Column1] = 123 进行查询。这可以通过原始索引完美解决。新索引也可用于此目的,但根据实现方式,即使未使用它们,也需要读取索引中 [Column2] 的值。

    所以是的:理论上删除索引可能有一个缺点:增加读取。

    [9 月 9 日更新]
    最近我遇到了另一种情况,即单个索引可以比组合索引更好
    考虑一个带有 [status]、[createdate] 列和其他一些字段的巨大表“错误”。大多数错误将被关闭,因此假设状态为“0”(打开)100 条记录和“1”(关闭)99000 条记录。

    SELECT * FROM bugs WHERE status = '0' 将从status 上的索引中受益匪浅,而SELECT * FROM bugs WHERE status = '1' 上的status 上的索引将无济于事。

    Oracle 会知道其中的区别,因为它会在索引上构建统计信息。

    但是,对于 status, createdate 上的组合索引,每个索引条目几乎都是唯一的,Oracle 将决定不将索引用于查询 SELECT * FROM bugs WHERE status = '0',因为它(错误地)猜测索引没有帮助。

    因此在这种情况下,不应仅仅因为它是组合索引的前缀而删除单个索引。

    注意:理论上,Oracle 可以在索引上构建更智能的统计信息,但它似乎没有这样做。

    【讨论】:

    • 在任何 Oracle 文档中是否有指向此的链接?预计会出现什么样的性能下降?
    • 不知道任何文档,只是我对我如何理解索引如何工作的解释。索引中有两列会使总索引增加一倍。当索引非常有选择性(或唯一性)时,Oracle 通常只需要读取几个“块”即可获得所需的所有信息。当索引是两倍大时,它可能需要读取更多块。但是,我认为在所有实际情况下效果都可以忽略不计。
    • +1。我认为这很明显,我很惊讶你没有得到更多的选票。如果您的索引更大,并且包含并非每个查询都需要的信息,那么在某些情况下肯定会降低性能。
    • 正如我的回答中提到的,始终测试更改的影响。我自己对此进行了测试,因为我对实际影响感到好奇。以下是结果(在测试之间刷新缓冲区缓存,5m 条记录):使用非唯一列,无索引:3.240s,col1 索引:0.025s,col1&2 索引:0.494s。使用唯一列,无索引:1.962s,col1 索引:0.004s,col1&2 索引:0.391s。超过 500 万条记录存在没有特定 col1 索引的影响,因此考虑记录数量并与您的数据库进行比较,它可能会或可能不会在您的应用程序中被注意到。
    • 顺便说一句,我关于文档的问题是希望 Oracle 可能提供一些方法来计算性能下降,而不仅仅是直接测试影响。 :-)
    【解决方案3】:

    不删除原始索引的危害是,Oracle 在只需要一个索引时维护两个索引的开销。

    离开它们的缺点是 CRUD 操作在您的表上的性能下降,我从您的帖子中意识到,目前这可能是“微不足道的”,但表会随着时间的推移而增长,并且在未来这可能会给您带来以下问题然后必须进行补救。

    它还会不必要地占用更多存储空间。

    您之前的程序仍然可以使用新索引。

    留下不必要的索引会使未来必须支持您的数据库的开发人员和 DBA 感到困惑,从而花费他们时间和精力来调查重复索引存在的原因。

    与其寻找不删除原始索引的理由,我会寻找保留它的理由。

    删除它,测试您的“其他”程序的性能,您应该会发现差别不大,如果有问题,您可以调查原因并在必要时更换它。

    【讨论】:

      猜你喜欢
      • 2020-08-18
      • 2012-04-28
      • 2019-07-05
      • 2016-07-19
      • 2012-10-12
      • 1970-01-01
      • 1970-01-01
      • 2013-08-23
      • 2016-05-05
      相关资源
      最近更新 更多