2026-04-14 18:09:52
Oracle 12c 的延迟索引维护特性
在 Oracle 12c 中,延迟全局索引维护(Delayed Global Index Maintenance)是一个重要的新特性,它解决了在分区表中维护全局索引时的性能问题。
一、延迟全局索引维护的定义
在分区表中,如果创建了全局索引,当对分区进行删除、截断等操作时,全局索引会失效,除非使用 UPDATE GLOBAL INDEXES 关键字同时维护索引。然而,这样做可能会导致分区维护操作变得非常缓慢。为了解决这个问题,Oracle 12c 引入了延迟全局索引维护特性,允许将索引维护工作异步延迟进行。
二、延迟维护的全局索引在查询中的状态
延迟维护的全局索引在查询中仍然会生效,但查询性能可能会受到影响。具体来说,当索引中存在孤儿条目(由于分区删除或截断等操作产生的无效索引条目)时,查询会利用一个内部函数 TBL$OR$IDX$PART$NUM 对 ROWID 进行判断过滤,以确保不会使用这些孤儿条目。这个过程会增加递归调用的数量,从而影响查询性能。
为了验证这一点,可以创建一个全局索引,然后删除一个分区并检查索引状态。在 dba_indexes 视图中,orphaned_entries 字段会记录索引中是否存在孤儿条目。即使存在孤儿条目,索引的状态仍然是 VALID,但在查询执行计划中,会看到一个额外的谓词过滤条件,用于过滤掉这些孤儿条目。
三、PMO_DEFERRED_GIDX_MAINT_JOB 的工作原理
延迟全局索引维护任务是通过 SYS.PMO_DEFERRED_GIDX_MAINT_JOB 实现的,该任务默认在每天凌晨 02:00 运行。它调用 dbms_part 包中的 cleanup_gidx_internal 过程来清理索引中的孤儿条目。
可以检查 dba_scheduler_jobs 视图来查看 PMO_DEFERRED_GIDX_MAINT_JOB 的执行情况和运行历史。如果需要,也可以手动调用 dbms_part.cleanup_gidx_internal 过程来立即清理索引中的孤儿条目,从而恢复查询性能。
四、TBL$OR$IDX$PART$NUM 函数的作用
TBL$OR$IDX$PART$NUM 是一个内部函数,用于确定特定记录所属的分区。在查询中,当需要过滤掉孤儿条目时,会调用这个函数来判断记录所属的分区,并据此过滤掉不属于当前分区的记录。这个函数没有公开的文档说明,但可以通过测试来验证其功能和用法。
五、总结
Oracle 12c 的延迟全局索引维护特性允许将索引维护工作异步延迟进行,从而避免了在分区维护时同时更新全局索引导致的性能问题。虽然延迟维护的全局索引在查询中仍然会生效,但可能会因为孤儿条目的存在而影响查询性能。为了解决这个问题,可以定期运行 PMO_DEFERRED_GIDX_MAINT_JOB 任务或手动调用 dbms_part.cleanup_gidx_internal 过程来清理索引中的孤儿条目。同时,了解 TBL$OR$IDX$PART$NUM 函数的作用也有助于更好地理解查询性能优化的过程。



