Disclaimer

Wednesday, 20 January 2021

Index Fragmentation Query

 set termout off verify off


define owner='DEMO'         -- table owner

define table='DEMOTABLE'    -- table name

define index='DEMOINDEX'    -- index name

define buckets=10           -- number of buckets

define sample=100           -- 100% scans all the index


column "free" format A5


variable c refcursor;


declare

 o all_indexes.owner%TYPE:='&owner';

 t all_indexes.table_name%TYPE:='&table';

 i all_indexes.table_name%TYPE:='&index';

 oid all_objects.object_id%TYPE;

 hsz varchar2(2000);

 n number:=&buckets;

 p number:=&sample;

 s varchar2(2000):='';

 k_min varchar2(2000);

 k_max varchar2(2000);

 k_lst varchar2(2000);

 k_nul varchar2(2000);

 k_vsz varchar2(2000);

 p_sam varchar2(2000):='';

 cursor cols is select i.column_name,i.column_position,case when data_type in ('VARCHAR2','RAW') then 3 else 1 end length_bytes

  from dba_ind_columns i join dba_tab_columns t 

  on (t.owner=i.table_owner and t.table_name=i.table_name and t.column_name=i.column_name)

  where i.table_owner=o and i.table_name=t and i.index_name=i order by column_position;

 procedure add(l in varchar2,i number default 0) is begin s:=s||chr(10)||rpad(' ',i)||l; end;

begin

 select object_id into oid from dba_objects where object_type='INDEX' and owner=o and object_name=i;

 /* Note:10640.1: block header size = fixed header (113 bytes) + variable transaction header (23*initrans) */

 select nvl(to_char(block_size - 113 - ini_trans*23),'null') header_size into hsz 

  from dba_indexes left outer join dba_tablespaces using (tablespace_name) where owner=o and index_name=i;

 for c in cols loop

  if ( c.column_position > 1 ) then k_lst:=k_lst||',' ; k_min:=k_min||',';k_max:=k_max||','; k_nul:=k_nul||' and ' ; k_vsz:=k_vsz||'+' ; end if;

  k_lst:=k_lst||c.column_name;

  k_nul:=k_nul||c.column_name|| ' is not null';

  k_min:=k_min||'min('||c.column_name||') '||c.column_name;

  k_max:=k_max||'max('||c.column_name||') '||c.column_name;

  k_vsz:=k_vsz||'nvl(vsize('||c.column_name||'),1)+'||c.length_bytes;

 end loop;

 if p != 100 then p_sam:='sample block('||p||')'; end if;

 add('with leaf_blocks as (',0);

 add('select /* cursor_sharing_exact dynamic_sampling(0) no_monitoring',1);

 add(' no_expand index_ffs('||t||','||i||') noparallel_index('||t||','||i||') */',10);

 add(k_min||','||1/(p/100)||'*count(rowid) num_rows',1);

 add(','||1/(p/100)||'*sum(1+vsize(rowid)+'||k_vsz||') vsize',1);

 add('from '||o||'.'||t||' '||p_sam||' '||t,1);

 add('where '||k_nul,1);

 add('group by sys_op_lbid('||oid||',''L'',rowid)',1);

 add('),keys as (',0);

 add('select ntile('||n||') over (order by '||k_lst||') bucket,',1);

 add(k_min||',',2);

 add('count(*) leaf_blocks, count(*)*'||hsz||' tsize,',2);

 add('sum(num_rows) num_rows,sum(vsize) vsize',2);

 add('from leaf_blocks group by '||k_lst,1);

 add(')',0);

 add('select '||k_min||',''->'' "->",'||k_max||',round(sum(num_rows)/sum(leaf_blocks)) "rows/block"',0);

 add(',round(sum(vsize)/sum(leaf_blocks)) "bytes/block",',1);

 add('case when sum(vsize)<=sum(tsize) then 100*round(1- sum(vsize) / (sum(tsize)),2) else null end "%free space",',1);

 add(' sum(leaf_blocks) "blocks",');

 --add('case when sum(vsize)<=sum(tsize)/2 then substr(rpad(''o'',5*round(1- sum(vsize) / (sum(tsize)),2),''o''),1,5) end "free"',1);

 add('substr(rpad(''o'',5*round(1- sum(vsize) / (sum(tsize)),2),''o''),1,5) "free"',1);

 add('from keys group by bucket order by bucket',0);

 begin open :c for s ; exception when others then dbms_output.put_line(s); raise; end ;

 dbms_output.put_line(s);

end;

/

set termout on 

print c


No comments:

Post a Comment

Understanding SQL Plan Baselines in Oracle Database

  Understanding SQL Plan Baselines in Oracle Database SQL Plan Baseline is the feature in Oracle started from Database 11g that helps to pre...