Вы находитесь на странице: 1из 5

Index Monitoring and Foreign Key Indexes By Richard Foote

One of the important questions regarding indexes is are they actually being used within the application or are they sitting there looking pretty not being used, wasting valuable resources and storage. One possible method of determining whether an index is being used is to set the MONITORING USAGE attribute of the index. This will place the index in the v$object_usage view and will flag the index as being used when indeed the Cost Based Optimizer (CBO)decides to use the index within an execution plan. Lets create a simple little table and associated index as an example:

SQL> create table daddy (id number constraint daddy_pk primary key, name varchar2(20)); Table created. SQL> insert into daddy values (1, BOWIE); 1 row created. SQL> insert into daddy values (2, ZIGGY); 1 row created. SQL> insert into daddy values (3, THIN WHITE DUKE); 1 row created. SQL> commit; Commit complete. SQL> alter index daddy_pk monitoring usage; Index altered.

If we look at the v$object_usage view, well now see an entry for this index, with the USED flag currently set to NO:

SQL> select * from v$object_usage where index_name = 'DADDY_PK'; INDEX_NAME TABLE_NAME MON USE START_MONITORING END_MONITORING ------------ ------------ --- --- ------------------- ------------------DADDY_PK DADDY YES NO 09/11/2008 17:24:23

If we however make the CBO use this index:

SQL> select * from daddy where id = 1; ID NAME ---------- -------------------1 BOWIE Execution Plan ---------------------------------------------------------Plan hash value: 2873139052 ---------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 25 | 1 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| DADDY | 1 | 25 | 1 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | DADDY_PK | 1 | | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------2 - access("ID"=1) Statistics ---------------------------------------------------------215 recursive calls 3 db block gets 36 consistent gets 0 physical reads 556 redo size 465 bytes sent via SQL*Net to client 396 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 6 sorts (memory) 0 sorts (disk) 1 rows processed

We now notice that the index is now marked as having been used:

SQL> select * from v$object_usage where index_name = 'DADDY_PK'; INDEX_NAME TABLE_NAME MON USE START_MONITORING END_MONITORING ------------ ------------ --- --- ------------------- ------------------DADDY_PK DADDY YES YES 09/11/2008 17:24:23

Although it doesnt give any indication on just how often the index is actually used, if an index is still marked as unused for a period of time, it does provide some indication that the index has not been used during that time and is a candidate for being dropped. Or does it? Unfortunately, there are some cases when an index is actually being used but monitoring the index doesnt give any such indication. However dropping such indexes can prove disastrous

For example, lets create another table that has a Foreign Key which references this DADDY table:

SQL> create table kiddie (id number, name varchar2(20), fk number, constraint kiddie_fk foreign key(fk) references daddy(id)); Table created.

Lets now populate it with a number of rows:

SQL> insert into kiddie select rownum, MAJOR TOM, 1 from dual connect by level <= 1000000; 1000000 rows created. SQL> commit; Commit complete.

Lets now create an index on the Foreign Key column and collect some stats:

SQL> create index kiddie_fk_i on kiddie(fk); Index created. SQL> exec dbms_stats.gather_table_stats(ownname=>null, tabname=>DADDY, estimate_percent=>null, cascade=>true, method_opt=> FOR ALL COLUMNS SIZE 1'); PL/SQL procedure successfully completed. SQL> exec dbms_stats.gather_table_stats(ownname=>null, tabname=>KIDDIE, estimate_percent=>null, cascade=>true, method_opt=> FOR ALL COLUMNS SIZE 1'); PL/SQL procedure successfully completed.

Lets now monitor this index on the Foreign Key and see where it may or may not get used:

SQL> alter index kiddie_fk_i monitoring usage; Index altered. SQL> select * from v$object_usage where index_name = 'KIDDIE_FK_I'; INDEX_NAME TABLE_NAME MON USE START_MONITORING END_MONITORING ------------ ---------- --- --- ------------------- ------------------KIDDIE_FK_I KIDDIE YES NO 09/10/2008 12:10:52

OK, lets now delete a row from the parent table and look at the statistics to see how many consistent reads were performed:

SQL> delete daddy where id = 2; 1 row deleted. Execution Plan ---------------------------------------------------------Plan hash value: 644713069 ---------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------| 0 | DELETE STATEMENT | | 1 | 3 | 0 (0)| 00:00:01 | | 1 | DELETE | DADDY | | | | | |* 2 | INDEX UNIQUE SCAN| SYS_C009714 | 1 | 3 | 0 (0)| 00:00:01 | ---------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------2 - access("ID"=2) Statistics ---------------------------------------------------------172 recursive calls 8 db block gets 26 consistent gets 1 physical reads 0 redo size 675 bytes sent via SQL*Net to client 554 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 5 sorts (memory) 0 sorts (disk) 1 rows processed

Now, behind the scenes, Oracle indeed used the index on the Foreign Key to determine whether or not the parent row could be safely deleted or whether there were child records that were still referencing the parent row. Note we used just 26 consistent reads. Lets see if the monitoring of the index has picked this up

SQL> select * from v$object_usage where index_name = 'KIDDIE_FK_I'; INDEX_NAME TABLE_NAME MON USE START_MONITORING END_MONITORING ------------ ---------- --- --- ------------------- ------------------KIDDIE_FK_I KIDDIE YES NO 09/10/2008 12:10:52

Ooops, this is not good. Is this index really not being used, is it really perhaps safe to drop. Lets find out:

SQL> drop index kiddie_fk_i; Index dropped.

Lets now delete another parent row and see if we notice a difference in performance:

SQL> delete daddy where id = 3; 1 row deleted. Execution Plan ---------------------------------------------------------Plan hash value: 644713069 ---------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------| 0 | DELETE STATEMENT | | 1 | 3 | 0 (0)| 00:00:01 | | 1 | DELETE | DADDY | | | | | |* 2 | INDEX UNIQUE SCAN| SYS_C009714 | 1 | 3 | 0 (0)| 00:00:01 | ---------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------2 - access("ID"=3) Statistics ---------------------------------------------------------186 recursive calls 7 db block gets 3194 consistent gets 1599 physical reads 736 redo size 675 bytes sent via SQL*Net to client 554 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 6 sorts (memory) 0 sorts (disk) 1 rows processed

Ooops, the consistent gets have jumped up dramatically from 26 to a massive 3194 !! Without the index on the Foreign Key, the only way now for Oracle to check whether its OK to delete a parent row is to perform a Full Table Scan on the child table. Not only is this potentially very costly but there could be some nasty locking implications as well. Index Monitoring only tells you if an index has been used or if it hasnt been used by the CBO within an execution plan. It doesnt however tell you whether an index is actually been used within the database or whether its indeed safe to drop the index. Therefore, the results from index monitoring needs to be used with caution.

Вам также может понравиться