基础知识 | Oracle Index Split(索引分裂:你的数据库越来越慢可能与此有关!建议排查!

为了不错过每一期干货,强烈建议关注我

写技术文章,纯属"为爱发电";更新不易,希望大家能够多多支持

1️⃣ 点赞的人,今年都升职加薪了

2️⃣ 点在看人,今年一定会发财

3️⃣ 评论区交流技术,每条留言都会回复

Oracle索引分裂的一些基础知识

索引分裂是Oracle B树索引在数据插入或更新时,为容纳新数据而必须进行的空间管理操作。它是索引保持数据有序和高效检索能力的核心机制,但会带来额外的I/O开销。

1. 索引分裂是什么?

当一个新的键值需要插入到一个已满的索引叶块中时,Oracle会创建新的索引块,并将原块中的部分条目重新分配,这个过程称为分裂。

  • 触发条件:索引叶块没有足够的空闲空间存放新条目。
  • 根本目的:维持B树结构的平衡与数据有序性。

2. 分裂的两种主要类型

根据新值在索引键顺序中的位置,Oracle采用两种算法:

2.1 90-10分裂(右侧分裂)

  • 场景 :新插入的值是当前索引中的最大值(常见于顺序插入,如使用递增序列)。
  • 过程
    1. 创建新叶块。
    2. 将原满块中约90%的旧数据复制到新块。
    3. 新最大值放入另一新块(或调整后的原块)。
    4. 原块升级为指向新块的分支块。
  • 逻辑:为后续的顺序插入预留空间。

2.2 50-50分裂(中间/左侧分裂)

  • 场景 :新插入的值不是最大值(常见于随机插入或更新)。
  • 过程
    1. 创建两个新叶块。
    2. 将原满块的条目按中间值大致均分。
    3. 较小一半放入一个叶块,较大一半连同新值放入另一个叶块。
    4. 更新分支块指针。
  • 逻辑:在随机插入模式下均衡分布数据,减少未来分裂。

3. 分裂对索引层级的影响

一个关键点是:并非所有分裂都会增加树的高度(BLEVEL)

  • 叶块或分支块分裂 :仅在同级增加新块,使树更"茂密",但深度(BLEVEL)不变
  • 根块分裂 :只有当根块自身填满时才会发生。此时:
    • 当前根块分裂成两个新分支块。
    • 原根块升级为新根块(地址不变)。
    • 这是导致BLEVEL增加(树长高)的唯一情况

4. 分裂带来的性能影响

分裂操作本身及结果可能引发以下问题:

  1. 即时开销:需要额外的I/O(读原块、写新块、更新指针)和CPU资源。
  2. 逻辑读增加:分裂可能导致顺序的逻辑行在物理上变得不连续,增加范围扫描时的随机I/O。
  3. 热点块争用
    • 在高并发顺序插入场景下(如使用序列),所有插入都指向"最右侧叶块",导致频繁的90-10分裂。
    • 引发 buffer busy waitsenq: TX - index contention 等等待事件,在RAC环境中尤为严重。
  4. 更新操作的影响:对索引列的更新实质是"删除旧值+插入新值",若新值导致目标叶块满,同样触发分裂。

5. 识别与监控索引分裂

识别分裂活动(频率)

  • 动态性能视图 :监控 V$SYSSTAT / V$SESSTAT 中的统计项:
    • leaf node splits(叶节点分裂)
    • branch node splits(分支节点分裂)
    • 计数值增长表明分裂频繁。
sql 复制代码
SELECT sn.name, ss.value
FROM V$SESSTAT ss, V$STATNAME sn
WHERE ss.statistic# = sn.statistic#
  AND sn.name LIKE '%node%split%';
有空自己看看  
leaf node splits	    0
leaf node 90-10 splits	0  

识别分裂结果(结构)

  • 数据字典视图 :查询 DBA_INDEXES
    • BLEVEL:若增加,则表明发生了根块分裂,树已长高。
    • LEAF_BLOCKS:异常快速增长可能暗示频繁的50-50分裂。
  • 注意CLUSTERING_FACTOR(聚簇因子)恶化是分裂可能导致的后果之一(增加范围扫描I/O),而非直接指标。

6. 管理策略与最佳实践

处理目标是管理其负面影响,而非阻止分裂(这是正常机制)。

A. 预防与优化(减少分裂频率和影响)

1) 合理设计索引键

* 避免右侧热点 :对顺序递增的主键,考虑使用反向键索引(Reverse Key Index)哈希分区全局索引 ,将插入打散到不同块中。

* 选择高选择性列:使条目分布更分散。

2) 优化存储

* 使用更大的数据块 :为索引表空间使用更大的块(如32KB),使每块容纳更多条目,显著降低分裂频率。需权衡对全表扫描的影响。

* 设置合理PCTFREE:创建/重建索引时为未来更新预留空间,延迟分裂。

3) 应用设计

* 优化序列插入 :对序列生成的键,增大序列CACHE并使用NOORDER选项,分散不同会话/实例的插入区间(RAC环境关键建议)。

* 利用分区:对大表使用分区索引,将维护工作分散到更小单元。

B. 修复与维护(重整现有碎片)

1) 优先使用索引合并(COALESCE

* 命令ALTER INDEX ... COALESCE;

* 优点 :在线操作,仅合并同一分支下相邻叶块的空闲空间,不改变BLEVEL,开销远小于重建。官方建议优先考虑此操作

2) 谨慎进行索引重建(REBUILD

* 命令ALTER INDEX ... REBUILD [ONLINE] ...;

* 核心警告

* 不要定期预防性重建 :重建后索引会进入新的分裂周期,可能陷入"重建-分裂-再重建"的循环。应基于确切诊断。

* 正确处理损坏索引 :对于损坏的索引,避免使用ALTER INDEX ... REBUILD (它可能读取坏块)。应使用CREATE INDEX ... DROPREBUILD ONLINE

* 注意分区索引 :对分区索引,可重建单个分区。对分区表进行SPLITMOVE等操作会导致关联的全局索引失效,必须重建。

3) 表重组 :若CLUSTERING_FACTOR极高且影响扫描性能,仅重建索引无效,需按索引键顺序重组基表。

官方处理流程总结

1)诊断先行 :依据leaf node splits统计、BLEVEL变化等判断问题,勿假设需重建。

2)优先合并 :对空间碎片,首选COALESCE

3)谨慎重建 :仅在合并无效、索引损坏或需迁移时进行,优先使用ONLINE选项。

4)分区索引特别注意 :分区维护操作可能导致全局索引失效,需及时重建或使用UPDATE GLOBAL INDEXES子句。

5)治本之策:通过优化应用设计(如哈希分区、增大序列缓存)从根源减少争用与过度分裂。

参考文档

复制代码
How Btree Indexes Are Maintained KB121622
How to build a partitioned Index step by step KB138406
How Does the Index Block Splitting Mechanism Work for B*tree Indexes? KB111575
How To Validate Index Block Split KB127304
重建与合并的官方建议:《索引重建的必要性与影响 (Doc ID 1525787.1)》
损坏索引的特定处理:《处理 Oracle 块损坏 (Doc ID 1526911.1)》
相关推荐
知识分享小能手2 小时前
Oracle 19c入门学习教程,从入门到精通,Oracle 控制文件与日志文件管理详解(8)
数据库·学习·oracle
走遍西兰花.jpg2 小时前
gaussdb的基础命令
数据库·gaussdb
阿杰 AJie2 小时前
MyBatis-Plus 的内置方法
java·数据库·mybatis
23124_802 小时前
Base64多层嵌套解码
前端·javascript·数据库
前进的李工2 小时前
SQL数据操作实战指南
数据库·sql·mysql
橘橙黄又青2 小时前
MyBatis篇
数据库·oracle·mybatis
TDengine (老段)2 小时前
TDengine R 语言连接器进阶指南
大数据·开发语言·数据库·r语言·时序数据库·tdengine·涛思数据
不会kao代码的小王2 小时前
深信服超融合 HCI 核心技术解析:aSV、aSAN 与 aNET 的协同架构
运维·服务器·网络·数据库·github