--创建测试表并插入数据
create table products
   (prod_id number(3),
    prod_name_code varchar2(5));
 
insert into products values(1,'aaaaa');
insert into products values(2,'bbbbb');
insert into products values(3,'ccccc');
insert into products values(4,'ddddd');
commit;
--创建主键(索引)
alter table products
   add (constraint products_pk primary key (prod_id));

SQL> --检索,没有数据
SQL> select index_name,monitoring,used,start_monitoring,end_monitoring
  2     from v$object_usage;
 
INDEX_NAME                     MONITORING USED START_MONITORING    END_MONITORING
------------------------------ ---------- ---- ------------------- -------------------

--开启对索引的监控
SQL> alter index products_pk monitoring usage;
 
Index altered

--检索,发现视图中已经监控此索引,但是次索引未使用
SQL> select index_name,monitoring,used,start_monitoring,end_monitoring
  2  from v$object_usage;
 
INDEX_NAME                     MONITORING USED START_MONITORING    END_MONITORING
------------------------------ ---------- ---- ------------------- -------------------
PRODUCTS_PK                    YES        NO   01/04/2017 09:30:26
 
--select使用此索引
SQL> select * from products where prod_id=2;
 
PROD_ID PROD_NAME_CODE
------- --------------
      2 bbbbb

--检索,此索引未已使用
SQL> select index_name,monitoring,used,start_monitoring,end_monitoring
  2  from v$object_usage;
 
INDEX_NAME                     MONITORING USED START_MONITORING    END_MONITORING
------------------------------ ---------- ---- ------------------- -------------------
PRODUCTS_PK                    YES        YES  01/04/2017 09:30:26

--关闭对索引的监控 
SQL> alter index products_pk nomonitoring usage;
 
Index altered

--查询视图,对此索引的监控已关闭
SQL> select index_name,monitoring,used,start_monitoring,end_monitoring
  2  from v$object_usage;
 
INDEX_NAME                     MONITORING USED START_MONITORING    END_MONITORING
------------------------------ ---------- ---- ------------------- -------------------
PRODUCTS_PK                    NO         YES  01/04/2017 09:30:26 01/04/2017 09:38:06
 
那如果要监控整个数据库的索引呢?难道要一条条这样写么?
回答是肯定的,只不过来个语句的拼接。
select 'alter index ' || owner || '.' || index_name || ' monitoring usage;'
  from dba_indexes
 where owner  in ('LM', 'LM2');    --MOS上为not in('SYS','SYSTEM');个人认为,用in将需要监控的用户写进去更靠谱点

将monitoring改为nomonitoring就生成了禁用监控的脚本:

select 'alter index ' || owner || '.' || index_name || ' nomonitoring usage;'
  from dba_indexes
 where owner  in ('LM', 'LM2');

基本类似上面单索引的方法,业务正常跑一段时间后,最后检测未被使用的索引,然后根据需求进行处理:

select d.owner, v.index_name
  from dba_indexes d, v$object_usage v
 where v.used = 'NO'
   and d.index_name = v.index_name;

参考MOS文章:Identifying Unused Indexes (Doc ID 144070.1)
无觅关联推荐,快速提升流量