WHY IS INDEX MONITORING REQUIRED?
Keeping a lot of indexes on a table, can affect the performance of the transaction like insert, update, delete on the table. i.e if we are inserting a new ROW, a new entry will be added to the indexes on that table. So the best way is to remove the unused indexes from the tables. But how will you find out what are the unused indexes?? Well, index monitoring feature will come to our rescue.
ALTER INDEX MONITORING USAGE; — Enable monitoring of the index
ALTER INDEX NOMONITORING USAGE; — Disable monitoring of the index
v$object_usage
view tracks information about the index usage.
DEMO:
Created an index:
SQL> desc EMPTABLE2 Name Null? Type ----------------------------------------- -------- ---------------------------- OWNER VARCHAR2(128) OBJECT_NAME VARCHAR2(128) SUBOBJECT_NAME VARCHAR2(128) OBJECT_ID NUMBER DATA_OBJECT_ID NUMBER SQL> create index IND_EMP on EMPTABLE2 (owner); Index created.
— Run a query that will use the index .
SQL> select count(*) from EMPTABLE2 where owner='SYS'; COUNT(*) ---------- 51473 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 66 | 39 (3)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 66 | | | |* 2 | INDEX FAST FULL SCAN| IND_EMP | 55836 | 3598K| 39 (3)| 00:00:01 | --------------------------------------------------------------------------------- SQL> select INDEX_NAME,monitoring,USED,start_monitoring from v$object_usage where index_name='IND_EMP'; no rows selected
We can see, v$object_usage
is not reporting any.
Lets enable monitoring for the index.
SQL> SQL> alter index IND_EMP monitoring usage; Index altered. SQL> set pagesize 200 set lines 929 col index_name for a18 col monitoring for a18 col used for a16 select INDEX_NAME,monitoring,USED,start_monitoring from v$object_usage where index_name='IND_EMP'; INDEX_NAME MONITORING USED START_MONITORING ------------------ ------------------ ---------------- ------------------- IND_EMP YES NO 08/01/2017 12:57:57
MONITORING: YES ( It shows monitoring is enabled )
USED : NO (It shows index has not been used yet)
Lets run the same query that uses index:
SQL> select count(*) from EMPTABLE2 where owner='SYS'; COUNT(*) ---------- 51473 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 66 | 39 (3)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 66 | | | |* 2 | INDEX FAST FULL SCAN| IND_EMP | 55836 | 3598K| 39 (3)| 00:00:01 | --------------------------------------------------------------------------------- SQL> select INDEX_NAME,monitoring,USED,start_monitoring from v$object_usage where index_name='IND_EMP'; INDEX_NAME MONITORING USED START_MONITORING ------------------ ------------------ ---------------- ------------------- IND_EMP YES YES 08/01/2017 12:57:57
Now USED
column is changed to YES. I.e someone has used the IND_EMP
index.
To view the information in the V$OBJECT_USAGE
view you have to be connected as the user owner of the objects you want to monitor, otherwise, you might not find the monitoring information you are looking for.
SQL> connect dbatest Enter password: all activities are audited Connected. SQL> select INDEX_NAME,monitoring,USED,start_monitoring from v$object_usage where index_name='IND_EMP'; no rows selected
As i have tried to access v$object_usage
for the user dbatest(not the owner of that index), it is not returning any rows.
Well there is a workaround :
Create the view as below:( AS SYS USER)
create or replace view ALL_OBJECT_USAGE (OWNER, INDEX_NAME, TABLE_NAME, MONITORING, USED, START_MONITORING, END_MONITORING) as select u.name, io.name, t.name, decode(bitand(i.flags, 65536), 0, 'NO', 'YES'), decode(bitand(ou.flags, 1), 0, 'NO', 'YES'), ou.start_monitoring, ou.end_monitoring from sys.user$ u, sys.obj$ io, sys.obj$ t, sys.ind$ i, sys.object_usage ou where i.obj# = ou.obj# and io.obj# = ou.obj# and t.obj# = i.bo# and u.user# = io.owner#; SQL> SQL> create public synonym ALL_OBJECT_USAGE FOR ALL_OBJECT_USAGE; Synonym created.
Now try to view the information from ALL_OBJECT_USAGE
table from dbatest user:
SQL> connect dbatest Enter password: all activities are audited Connected. SQL> select INDEX_NAME,monitoring,USED,start_monitoring fromcALL_OBJECT_USAGE where index_name='IND_EMP'; INDEX_NAME MONITORING USED START_MONITORING ------------------ ------------------ ---------------- ------------------- IND_EMP YES YES 08/01/2017 12:57:57
Voilla!!, I can see it 🙂
How to Disable monitoring:
SQL> alter index IND_EMP no monitoring usage; Index altered. SQL> select INDEX_NAME,monitoring,USED,start_monitoring from v$object_usage where index_name='IND_EMP'; INDEX_NAME MONITORING USED START_MONITORING ------------------ ------------------ ---------------- ------------------- IND_EMP NO YES 08/01/2017 12:57:57
CONCLUSION: So to find to unused indexes in the database, Enable monitoring for the indexes in the database for a period of time, then get the usage report either from
v$object_usage
orALL_OBJECT_USAGE
. Analyze the report with application team and take a decision to remove the unused ones.