在Oracle数据库长期运行的系统中,随着业务变更和字段调整,表中往往会积累大量不再被SQL语句使用的索引。这些无用索引不仅占用存储空间,还会在增删改操作时增加维护成本,拖慢写入性能。因此,建立一套可靠的索引监控与清理机制,是数据库运维中的基础工作。

开启索引监控识别潜在无用索引
Oracle提供了原生的索引监控功能,通过alter index语句可以让数据库记录该索引在一段时间内的使用情况。具体命令格式为alter index 索引名 monitoring usage,执行后Oracle会在内部跟踪所有针对该索引的访问。需要注意的是,监控本身对性能影响极小,因为它只做标记而不做复杂统计。
监控开启后,DBA应当选择一个覆盖完整业务周期的时间窗口,例如包含月末批处理、每日高频交易等典型场景的两到四周。如果只监控一天,可能会漏掉周期性使用的索引。以下示例展示如何对订单表上的三个索引开启监控:
alter index idx_orders_cust monitoring usage; alter index idx_orders_status monitoring usage; alter index idx_orders_create_date monitoring usage;
开启监控之后,所有索引的使用痕迹都会被写入数据字典。此时不能立刻判定未出现使用记录的索引就是垃圾,必须结合业务节奏来判断。有些报表索引只在季度结算时触发,短期监控容易误杀。
通过数据字典视图确认索引使用状态
监控数据集中在动态性能视图v$object_usage中,该视图记录了每个被监控索引的USED字段值。当USED为NO且监控起始时间已覆盖业务周期,就说明这段时间内优化器从未选择该索引。查询方式非常简单:
select index_name, table_name, monitoring, used, start_monitoring, end_monitoring from v$object_usage where used = 'NO';
为了更稳妥,还可以关联dba_indexes获取索引的创建时间、叶子块数量等,评估如果删除能释放多少空间。下表列出常见评估维度:
| 字段 | 含义 | 清理参考 |
|---|---|---|
| leaf_blocks | 索引叶子块数 | 越大越值得删 |
| distinct_keys | 不同键值数 | 过低可能是重复索引 |
| last_analyzed | 统计信息时间 | 久未分析需谨慎 |
在确认USED为NO后,建议先关闭监控以避免字典表无限增长,命令为alter index 索引名 nomonitoring usage。此后若仍不确定,可把候选索引改名而非直接删除,观察应用报错情况再最终处理。
安全清理无用索引的落地步骤
直接drop index存在风险,规范做法是在删除前备份索引定义与统计信息。可以使用dbms_metadata.get_ddl获取创建语句,并用dbms_stats.export_index_stats导出统计信息到备份表。这样一旦误删,能迅速重建并恢复优化器认知。
-- 获取索引DDL
select dbms_metadata.get_ddl('INDEX', 'IDX_ORDERS_STATUS') from dual;
-- 导出统计信息
exec dbms_stats.export_index_stats(ownname=>'SCOTT', indname=>'IDX_ORDERS_STATUS', stattab=>'IDX_BAK');
生产环境删除前,强烈建议先在测试库用真实业务流量回放验证。可以利用AWR报告对比删除前后SQL执行计划,确认没有关键语句退化为全表扫描。验证通过后,再在低峰期于生产执行drop index idx_orders_status。
清理完毕应重新收集表统计信息,保证优化器获得准确数据分布。整个流程形成闭环后,数据库写入延迟通常会明显下降,存储回收效果也直观可见。定期重复监控动作,可让索引体系随业务演进保持精简高效。
Oracleindex_monitoringunused_index修改时间:2026-08-16 16:08:23