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

Rebuilding Of Index

===================
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.

Reason to rebuild an index:


--------------------------
1. the reason to rebuild an index should be because of poor performance of your
queries using the index.

How to determine an index needs to be rebuilt?


---------------------------------------------
There are 2 thumb rules to determine if an index needs to be rebuilt.
1. If index has (HEIGHT > 4) or (BLEVEL > 3) --Height= BLEVEL+1
2. elIf the deleted leaf rows > 20%. i.e (DEL_LF_ROWS/LF_ROWS*100) is > 20.

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.

First analyze the suspect index


-------------------------------
Analyze index command and Validate Structure command should be executed to collect
statistics of index.

SQL> analyze index TEST_INDX validate structure; -- First analyze the suspect index

1. Indexes having BLEVEL > 3 or HEIGHT > 4


SQL> select owner, index_name, table_name, blevel from dba_indexes where
BLEVEL>3
or
SQL> SELECT name, height, lf_rows, del_lf_rows, (del_lf_rows/lf_rows)*100 as
ratio FROM INDEX_STATS;

2. The deleted leaf rows > 20%. i.e (DEL_LF_ROWS/LF_ROWS*100) is > 20.

SQL> SELECT name, height, lf_rows, del_lf_rows, (del_lf_rows/lf_rows)*100 as


ratio FROM INDEX_STATS;

Index Rebuild command


---------------------
1. alter index <index_name> rebuild;
2. You can rebuild indexes Online to prevent Lock and downtime.
ALTER INDEX <index name> REBUILD ONLINE;
3. Rebuild Indexes in parallel that are widely used in production environment will
speed up your job and finish in less time. It is recommended that you do not
give more parallel than your CPU count when using Parallel. Indexes can be rebuilt
in parallel and online as follows.

SQL> ALTER INDEX <index name> REBUILD ONLINE PARALLEL <parallel_count>;


SQL> ALTER INDEX MID_IX REBUILD ONLINE PARALLEL 4;

After Rebuilding of Index check


-------------------------------
1. Again analyze the index
ANALYZE INDEX <index_name> VALIDATE STRUCTURE;
2.Check the status
SELECT name,height,lf_rows,lf_blks,del_lf_rows,distinct_keys,used_space,
(del_lf_rows/lf_rows)*100 as ratio FROM INDEX_STATS;

Script to find Fragmented indexes:


=================================
set lines 500
col NEW_IDX_percentage 999.99999
col idxname format a38 head "Owner.Index"
col uniq format a01 head "U"
col tsname format a28 head "Tablespace"
col xtrblk format 999999 head "Extra|Blocks"
col lfcnt format 9999999 head "Leaf|Blocks"
col blk format 9999999 head "Curr|Blocks"
col currmb format 99999 head "Curr|MB"
col newmb format 99999 head "New|MB"

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;

Index Rebuild Procedure:


=======================

CREATE OR REPLACE PROCEDURE SYS.REBUILD_TABLE_INDEX (SCHEMANAME VARCHAR2)

AS

SQL_STR VARCHAR2(1000);

BEGIN

FOR CUROSR_INDEX IN (SELECT OWNER,SEGMENT_NAME from SYS.DBA_SEGMENTS

WHERE SEGMENT_TYPE='INDEX'

AND OWNER = SCHEMANAME


ORDER BY SEGMENT_NAME ) LOOP

BEGIN

SQL_STR:='ALTER INDEX '||CUROSR_INDEX.OWNER||'.'||CUROSR_INDEX.SEGMENT_NAME


||' REBUILD ONLINE NOLOGGING PARALLEL 8';

EXECUTE IMMEDIATE SQL_STR;

DBMS_OUTPUT.PUT_LINE('SUCCESS : '|| CUROSR_INDEX.OWNER||'.'||


CUROSR_INDEX.SEGMENT_NAME);

EXCEPTION WHEN OTHERS THEN

DBMS_OUTPUT.PUT_LINE('ERROR : '||CUROSR_INDEX.OWNER||'.'||
CUROSR_INDEX.SEGMENT_NAME||':'||SQLERRM);

END;

END LOOP;

END;

=========================================

Test the above procedure as below:

Following one is the SQL script (test.sql) to get all those jobs done.

Pass Parameter Schema name from UNIX OS.

conn / as sysdba

select name from v$database;

set serveroutput on;

set timing on;

set time on;

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

export Date=`date +%d%b%Y`.`date +%I`.`date +%M%p`

sqlplus /nolog @test.sql >> DBMaintenace_$Date.txt

You can create a corn job using above shell script (here test.sh) to get this
maintenance job done without any manual intervention.

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