Question: I need a dictionary script to
display all nulti-column indexes, all indexes with more than one
column. How can I display these indexes with concatenated
columns?
Answer: This
script will display all indexes that have more than one
column, and this script will show all columns within an
index. Multi-column indexes are sometime called composite
indexes and
composite indexing and column ordering are an important
part of Oracle tuning with indexes.
However, how can we tell if the
multi-column indexes are being used? You can also run
a related query to display the frequency that these
multi-column indexes are invoked, an important part of SQL
tuning. See the book
Advanced Oracle SQL Tuning for full details.
-- *******************************
-- Display composite indexes
-- *******************************
break on index_name skip 1
col index_name format a30
col column_name format a30
select
index_name,
column_position,
column_name
from
user_ind_columns i
where
(select
count(*)
from
user_ind_columns u
where
u.index_name = i.index_name) > 1
group by
index_name,
column_position,
column_name
order by
index_name,
column_position;
In the aggregate, this query can be used to display how
often a composite index is being used for a one month
period. This can help identify un-used indexes:
--
*********************************
-- Are composite indexes being used?
-- *********************************
select
to_char(sn.begin_interval_time,'yyyy-mm')
c1,
p.object_name c2,
p.search_columns c3,
count(*)
from
see code depot for
full script
dba_hist_snapshot sn,
dba_hist_sql_plan p,
dba_hist_sqlstat st
where
--
**************************************************
-- Only show data for multi-column
composite indexes
--
**************************************************
(select
count(*)
from
user_ind_columns u
where
u.index_name = p.object_name) > 1
and
st.sql_id = p.sql_id
and
sn.snap_id = st.snap_id
and
p.object_owner = 'PUBS'
and
--
************************************************
-- This is supposed to just show the
last 30 days
-- ************************************************
sysdate > sysdate - 30
group by
begin_interval_time,
object_name,
search_columns;
Once we see if composite indexes are being used, we can
drill-down an look at a list of all multi-column indexes.
--
***********************************************
-- Show frequency of use of
multi-column indexes
--
***********************************************
with
composite_index_name_list
as
(select
i.index_name
from
user_ind_columns i
where
(select
count(*)
from
user_ind_columns u
where
u.index_name = i.index_name) > 1
group by
index_name
order by
index_name)
select
to_char(sn.begin_interval_time,'yyyy-mm') c1,
p.object_name c2,
p.search_columns c3,
count(*)
from
see code depot for
full script
dba_hist_snapshot sn,
dba_hist_sql_plan p,
dba_hist_sqlstat st,
composite_index_name_list
i
where
--
****************************************************
-- Only show multi-column indexes from
the WITH clause
--
****************************************************
i.index_name =
p.object_name
and
st.sql_id = p.sql_id
and
sn.snap_id = st.snap_id
and
p.object_owner = 'PUBS'
and
--
************************************************
-- only for the last 30 days . . .
--
************************************************
sysdate > sysdate - 30
group by
begin_interval_time,
object_name,
search_columns;
For each index returned by this query, you can query AWR
and see how often an individual index was invoked:
col c1
heading 'Begin|Interval|time' format a20
col c2 heading 'Search
Columns' format 999
col c3 heading 'Invocation|Count'
format 99,999,999
break on c1 skip 2
accept idxname char
prompt 'Enter Index Name: '
ttitle 'Invocation
Counts for index|&idxname'
select
to_char(sn.begin_interval_time,'yy-mm-dd
hh24') c1,
p.search_columns c2,
count(*)
c3
from
see code depot
for full script
dba_hist_snapshot sn,
dba_hist_sql_plan p,
dba_hist_sqlstat st
where
st.sql_id
= p.sql_id
and
sn.snap_id
= st.snap_id
and
p.object_name = '&idxname'
group by
begin_interval_time,search_columns;