为了不错过每一期干货,强烈建议关注我
写技术文章,纯属"为爱发电";更新不易,希望大家能够多多支持
1️⃣ 点赞的人,今年都升职加薪了
2️⃣ 点在看人,今年一定会发财
3️⃣ 评论区交流技术,每条留言都会回复
Oracle索引分裂的一些基础知识
索引分裂是Oracle B树索引在数据插入或更新时,为容纳新数据而必须进行的空间管理操作。它是索引保持数据有序和高效检索能力的核心机制,但会带来额外的I/O开销。
1. 索引分裂是什么?
当一个新的键值需要插入到一个已满的索引叶块中时,Oracle会创建新的索引块,并将原块中的部分条目重新分配,这个过程称为分裂。
- 触发条件:索引叶块没有足够的空闲空间存放新条目。
- 根本目的:维持B树结构的平衡与数据有序性。
2. 分裂的两种主要类型
根据新值在索引键顺序中的位置,Oracle采用两种算法:
2.1 90-10分裂(右侧分裂)
- 场景 :新插入的值是当前索引中的最大值(常见于顺序插入,如使用递增序列)。
- 过程 :
- 创建新叶块。
- 将原满块中约90%的旧数据复制到新块。
- 新最大值放入另一新块(或调整后的原块)。
- 原块升级为指向新块的分支块。
- 逻辑:为后续的顺序插入预留空间。
2.2 50-50分裂(中间/左侧分裂)
- 场景 :新插入的值不是最大值(常见于随机插入或更新)。
- 过程 :
- 创建两个新叶块。
- 将原满块的条目按中间值大致均分。
- 较小一半放入一个叶块,较大一半连同新值放入另一个叶块。
- 更新分支块指针。
- 逻辑:在随机插入模式下均衡分布数据,减少未来分裂。
3. 分裂对索引层级的影响
一个关键点是:并非所有分裂都会增加树的高度(BLEVEL)。
- 叶块或分支块分裂 :仅在同级增加新块,使树更"茂密",但深度(BLEVEL)不变。
- 根块分裂 :只有当根块自身填满时才会发生。此时:
- 当前根块分裂成两个新分支块。
- 原根块升级为新根块(地址不变)。
- 这是导致BLEVEL增加(树长高)的唯一情况。
4. 分裂带来的性能影响
分裂操作本身及结果可能引发以下问题:
- 即时开销:需要额外的I/O(读原块、写新块、更新指针)和CPU资源。
- 逻辑读增加:分裂可能导致顺序的逻辑行在物理上变得不连续,增加范围扫描时的随机I/O。
- 热点块争用 :
- 在高并发顺序插入场景下(如使用序列),所有插入都指向"最右侧叶块",导致频繁的90-10分裂。
- 引发
buffer busy waits、enq: TX - index contention等等待事件,在RAC环境中尤为严重。
- 更新操作的影响:对索引列的更新实质是"删除旧值+插入新值",若新值导致目标叶块满,同样触发分裂。
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 ... DROP或REBUILD ONLINE。
* 注意分区索引 :对分区索引,可重建单个分区。对分区表进行SPLIT、MOVE等操作会导致关联的全局索引失效,必须重建。
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)》