From 8i onwards, you can now have index compression which you can read about here. Whilst in almost all circumstances, index compression yields better performance, determining the optimal index compression is non-trivial. The following utility takes a brute force approach by taking each index and applying the various compression levels and reporting the compression effectiveness of each.
Needless to say, this will grind away for some time and care should be taken when it is used.
Notes for use:
create or replace
package COMPRESSION_TEST is
procedure assessment(p_owner varchar2,
p_leaf_threshold number default 1000,
p_skip_analyze varchar2 default 'N',
p_percent number default null,
p_skip_suspected_synthetic varchar2 default 'Y',
p_sort_size number default null) ;
end;
/
create or replace
package body COMPRESSION_TEST is
procedure premlinary_analyze(p_owner varchar2, p_percent number default null) is
begin
for i in ( select 'analyze table '||owner||'.'||table_name||' estimate statistics'||
decode(p_percent,null,null,' sample '||p_percent||' percent')||' for table' ddl
from dba_tables
where owner = upper(p_owner)) loop
execute immediate i.ddl;
end loop;
for i in ( select 'analyze index '||p_owner||'.'||index_name||' estimate statistics'||
decode(p_percent,null,null,' sample '||p_percent||' percent') ddl
from dba_indexes
where owner = upper(p_owner)) loop
execute immediate i.ddl;
end loop;
end;
procedure assessment(p_owner varchar2,
p_leaf_threshold number default 1000,
p_skip_analyze varchar2 default 'N',
p_percent number default null,
p_skip_suspected_synthetic varchar2 default 'Y',
p_sort_size number default null) is
cursor index_list is
select di.index_name, max(dic.column_position)-decode(di.uniqueness,'UNIQUE',1,0) col_pos,
dt.num_rows, di.distinct_keys, di.leaf_blocks
from dba_indexes di,
dba_ind_columns dic,
dba_tables dt
where di.owner = upper(p_owner)
and di.leaf_blocks > p_leaf_threshold
and di.compression = 'DISABLED'
and dic.index_owner = di.owner
and dic.index_name = di.index_name
and dt.owner = di.table_owner
and dt.table_name = di.table_name
group by di.index_name, di.uniqueness, dt.num_rows, di.distinct_keys, di.leaf_blocks
having ( upper(p_skip_suspected_synthetic) = 'Y'
and ( max(dic.column_position) > 1
or di.uniqueness != 'UNIQUE'
or abs(dt.num_rows / di.distinct_keys -1 ) > 0.1 )
)
or upper(p_skip_suspected_synthetic) != 'Y';
v_analyze_clause varchar2(100) := ' estimate statistics ';
v_leaf_blocks number;
begin
if p_sort_size is not null then
execute immediate 'alter session set sort_area_size = '||p_sort_size;
execute immediate 'alter session set sort_area_retained_size = '||p_sort_size;
end if;
if p_skip_analyze not in ('N','n') then
premlinary_analyze(p_owner,p_percent);
end if;
if p_percent is not null then
v_analyze_clause := v_analyze_clause || 'sample '||p_percent||' percent';
end if;
for i in index_list loop
dbms_output.put_line('INDEX: '||i.index_name);
dbms_output.put_line('- Initial : '||i.leaf_blocks);
for j in 1 .. i.col_pos loop
execute immediate 'alter index '||p_owner||'.'||i.index_name||' rebuild compress '||j;
execute immediate 'analyze index '||p_owner||'.'||i.index_name||v_analyze_clause;
select leaf_blocks
into v_leaf_blocks
from dba_indexes
where owner = upper(p_owner)
and index_name = i.index_name;
dbms_output.put_line('- Compression '||j||': '||v_leaf_blocks);
end loop;
end loop;
end;
end;
/