Index Rebuilding
Index Rebuilding
===================
Symbols of Index Rebuilding
---------------------------
1. Indexes of a table may be corrupted,fragmented or unbalanced as a result of
intensive (large no. of) DML operations (insert,delete,update) of the table.
2. Indexes are broken and UNUSABLE when they are moved to new tablespaces.I moved
the table. This will cause all of the rowid values to change which means the
table's indexes need to be rebuilt.
3. Indexes that are always accessed vis an "index unique scan" will never need
rebuilding, because the "dead space" does not interfere with the index
access.
4. Rebuilding of index is required only on B-Tree indexes.
Action
======
1. We must first get an idea of the current state of the index by using the ANALYZE
INDEX VALIDATE STRUCTURE command.
2. The VALIDATE STRUCTURE command can be safely executed without affecting the
optimizer.
3. The VALIDATE STRUCTURE command populates the SYS.INDEX_STATS table only. The
SYS.INDEX_STATS table can be accessed with the public synonym INDEX_STATS. The
INDEX_STATS table will only hold validation information for one index at a time.
You will need to query this table before validating the structure of the next
index.
SQL> analyze index TEST_INDX validate structure; -- First analyze the suspect index
2. The deleted leaf rows > 20%. i.e (DEL_LF_ROWS/LF_ROWS*100) is > 20.
select
u.name ||'.'|| o.name idxname,
decode(bitand(i.property, 1), 0,' ', 1, 'x','?') uniq,
ts.name tsname,
seg.blocks blk,
i.leafcnt lfcnt,
floor((1 - i.pctfree$/100) * i.leafcnt - i.rowcnt * (sum(h.avgcln) + 11) / (8192 -
66 - i.initrans * 24) ) xtrblk,
round(seg.bytes/(1024*1024)) currmb,
(1 + i.pctfree$/100) * (i.rowcnt * (sum(h.avgcln) + 11) / (i.leafcnt * (8192 - 66 -
i.initrans * 24)) * seg.bytes/(1024*1024)) newmb,
((1 + i.pctfree$/100) * (i.rowcnt * (sum(h.avgcln) + 11) / (i.leafcnt * (8192 - 66
- i.initrans * 24)) * seg.bytes/(1024*1024)))*100/(seg.bytes/(1024*1024))
NEW_IDX_percentage,
(100-((1 + i.pctfree$/100) * (i.rowcnt * (sum(h.avgcln) + 11) / (i.leafcnt * (8192
- 66 - i.initrans * 24)) * seg.bytes/(1024*1024)))*100/(seg.bytes/(1024*1024)))
Benifit_percent
from
sys.ind$ i,
sys.icol$ ic,
sys.hist_head$ h,
sys.obj$ o,
sys.user$ u,
sys.ts$ ts,
dba_segments seg
where
i.leafcnt > 1 and
i.type# in (1,4,6) and -- exclude special types
ic.obj# = i.obj# and
h.obj# = i.bo# and
h.intcol# = ic.intcol# and
o.obj# = i.obj# and
o.owner# != 0 and
u.user# = o.owner# and
i.ts# = ts.ts# and
u.name = seg.owner and
o.name = seg.segment_name and
seg.blocks > i.leafcnt -- if i.leafcnt > seg.blocks then statistics are not up-to-
date
group by
u.name,
decode(bitand(i.property, 1), 0,' ', 1, 'x','?'),
ts.name,
o.name,
i.rowcnt,
i.leafcnt,
i.initrans,
i.pctfree$,
--p.value,
i.blevel,
i.leafcnt,
seg.bytes,
i.pctfree$,
i.initrans,
seg.blocks
having
50 * i.rowcnt * (sum(h.avgcln) + 11)
< (i.leafcnt * (8192 - 66 - i.initrans * 24)) * (50 - i.pctfree$) and
floor((1 - i.pctfree$/100) * i.leafcnt -
i.rowcnt * (sum(h.avgcln) + 11) / (8192 - 66 - i.initrans * 24) ) > 0 and
((1 + i.pctfree$/100) * (i.rowcnt * (sum(h.avgcln) + 11) / (i.leafcnt * (8192 - 66
- i.initrans * 24)) * seg.bytes/(1024*1024)))*100/(seg.bytes/(1024*1024)) <80
and round(seg.bytes/(1024*1024)) > 50
order by 10,9, 2;
AS
SQL_STR VARCHAR2(1000);
BEGIN
WHERE SEGMENT_TYPE='INDEX'
BEGIN
DBMS_OUTPUT.PUT_LINE('ERROR : '||CUROSR_INDEX.OWNER||'.'||
CUROSR_INDEX.SEGMENT_NAME||':'||SQLERRM);
END;
END LOOP;
END;
=========================================
Following one is the SQL script (test.sql) to get all those jobs done.
conn / as sysdba
exec REBUILD_TABLE_INDEX('schemaname');
exit
Use this shell Script (test.sh) to execute above SQL Command Set and get the output
in another file as job log.
#!/usr/bin/bash
export ORACLE_SID=testdbdp
export ORACLE_BASE=/oracle/app2
export ORACLE_HOME=/oracle/app2/11gr2/db_1
You can create a corn job using above shell script (here test.sh) to get this
maintenance job done without any manual intervention.