设为首页 收藏本站
查看: 753|回复: 0

[经验分享] Oracle 重建索引脚本

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-4-23 08:52:04 | 显示全部楼层 |阅读模式
  索引是提高数据库查询性能的有力武器。没有索引,就好比图书馆没有图书标签一样,找一本书自己想要的书比登天还难。然而索引在使用的过程中,尤其是在批量的DML的情形下会产生相应的碎片,以及B树高度会发生相应变化,因此可以对这些变化较大的索引进行重构以提高性能。N久以前Oracle建议我们定期重建那些高度为4,已删除的索引条目至少占有现有索引条目总数的20%的这些表上的索引。但Oracle现在强烈建议不要定期重建索引。具体可以参考文章:Oracle 重建索引的必要性。尽管如此重建索引还是有必要的,只是不建议定期。本文给出了重建索引的脚本供大家参考。

1、重建索引shell脚本
robin@SZDB:~/dba_scripts/custom/bin> more rebuild_unbalanced_indices.sh   
# +-------------------------------------------------------+  
# +    Rebulid unblanced indices                          |  
# +    Author : Leshami                                   |   
# +    Parameter : No                                     |  
# +    Blog : http://blog.iyunv.com/leshami                |   
# +-------------------------------------------------------+  

#!/bin/bash   
# --------------------  
# Define variable  
# --------------------  

if [ -f ~/.bash_profile ]; then  
. ~/.bash_profile  
fi  

DT=`date +%Y%m%d`;             export DT  
RETENTION=1  
LOG_DIR=/tmp  
LOG=${LOG_DIR}/rebuild_unbalanced_indices_${DT}.log  
DBA=Leshami@12306.cn  

# ------------------------------------  
# Loop all instance in current server  
# -------------------------------------  
echo "Current date and time is : `/bin/date`">>${LOG}  

for db in `ps -ef | grep pmon | grep -v grep |grep -v asm |awk '{print $8}'|cut -c 10-`  
do  
    echo "$db"  
    export ORACLE_SID=$db  
    echo "Current DB is $db" >>${LOG}  
    echo "===============================================">>${LOG}  
    $ORACLE_HOME/bin/sqlplus -S /nolog @/users/robin/dba_scripts/custom/sql/rebuild_unbalanced_indices.sql>>${LOG}  
done;  

echo "End of rebuilding index for all instance at : `/bin/date`">>${LOG}  
# -------------------------------------  
# Check log file   
# -------------------------------------  
status=`grep "ORA-" ${LOG}`  
if [ -z $status ];then  
    mail -s "Succeeded rebuilding indices on `hostname`  !!!" ${DBA} <${LOG}  
else  
    mail -s "Failed rebuilding indices on `hostname`  !!!" ${DBA} <${LOG}  
fi  

# ------------------------------------------------  
# Removing files older than $RETENTION parameter   
# ------------------------------------------------  

find ${LOG_DIR} -name "rebuild_unb*" -mtime +$RETENTION -exec rm {} \;  

exit  

2、重建索引调用的SQL脚本
robin@SZDB:~/dba_scripts/custom/sql> more rebuild_unbalanced_indices.sql   
conn / as sysdba  
set serveroutput on;  
DECLARE  
   resource_busy               EXCEPTION;  
   PRAGMA EXCEPTION_INIT (resource_busy, -54);  
   c_max_trial        CONSTANT PLS_INTEGER := 10;  
   c_trial_interval   CONSTANT PLS_INTEGER := 1;  
   pmaxheight         CONSTANT INTEGER := 3;  
   pmaxleafsdeleted   CONSTANT INTEGER := 20;  

   CURSOR csrindexstats  
   IS  
      SELECT NAME,  
             height,  
             lf_rows AS leafrows,  
             del_lf_rows AS leafrowsdeleted  
        FROM index_stats;  

   vindexstats                 csrindexstats%ROWTYPE;  

   CURSOR csrglobalindexes  
   IS  
      SELECT owner,index_name, tablespace_name  
        FROM dba_indexes  
       WHERE partitioned = 'NO'  
        AND owner IN ('GX_ADMIN');  

   CURSOR csrlocalindexes  
   IS  
      SELECT index_owner,index_name, partition_name, tablespace_name  
        FROM dba_ind_partitions  
       WHERE status = 'USABLE'  
        AND index_owner IN ('GX_ADMIN');  

   trial                       PLS_INTEGER;  
   vcount                      INTEGER := 0;  
BEGIN  
   trial := 0;  

   /* Global indexes */  
   FOR vindexrec IN csrglobalindexes  
   LOOP  
      EXECUTE IMMEDIATE  
         'analyze index ' || vindexrec.owner ||'.'|| vindexrec.index_name || ' validate structure';  

      OPEN csrindexstats;  

      FETCH csrindexstats INTO vindexstats;  

      IF csrindexstats%FOUND  
      THEN  
         IF    (vindexstats.height > pmaxheight)  
            OR (    vindexstats.leafrows > 0  
                AND vindexstats.leafrowsdeleted > 0  
                AND (vindexstats.leafrowsdeleted * 100 / vindexstats.leafrows) >  
                       pmaxleafsdeleted)  
         THEN  
            vcount := vcount + 1;  
            DBMS_OUTPUT.PUT_LINE (  
               'Rebuilding index ' || vindexrec.owner ||'.'|| vindexrec.index_name || '...');  

           <<alter_index>>  
            BEGIN  
               EXECUTE IMMEDIATE  
                     'alter index '  
                  || vindexrec.owner ||'.'  
                  || vindexrec.index_name  
                  || ' rebuild'  
                  || ' parallel nologging compute statistics'  
                  || ' tablespace '  
                  || vindexrec.tablespace_name;  
            EXCEPTION  
               WHEN resource_busy OR TIMEOUT_ON_RESOURCE  
               THEN  
                  DBMS_OUTPUT.PUT_LINE (  
                     'alter index - busy and wait for 1 sec');  
                  DBMS_LOCK.sleep (c_trial_interval);  

                  IF trial <= c_max_trial  
                  THEN  
                     GOTO alter_index;  
                  ELSE  
                     DBMS_OUTPUT.PUT_LINE (  
                           'alter index busy and waited - quit after '  
                        || TO_CHAR (c_max_trial)  
                        || ' trials');  
                     RAISE;  
                  END IF;  
               WHEN OTHERS  
               THEN  
                  DBMS_OUTPUT.PUT_LINE ('alter index err ' || SQLERRM);  
                  RAISE;  
            END;  
         END IF;  
      END IF;  

      CLOSE csrindexstats;  
   END LOOP;  

   DBMS_OUTPUT.PUT_LINE ('Global indices rebuilt: ' || TO_CHAR (vcount));  
   vcount := 0;  
   trial := 0;  

   /* Local indexes */  
   FOR vindexrec IN csrlocalindexes  
   LOOP  
      EXECUTE IMMEDIATE  
            'analyze index '  
         || vindexrec.index_owner||'.'  
         || vindexrec.index_name  
         || ' partition ('  
         || vindexrec.partition_name  
         || ') validate structure';  

      OPEN csrindexstats;  

      FETCH csrindexstats INTO vindexstats;  

      IF csrindexstats%FOUND  
      THEN  
         IF    (vindexstats.height > pmaxheight)  
            OR (    vindexstats.leafrows > 0  
                AND vindexstats.leafrowsdeleted > 0  
                AND (vindexstats.leafrowsdeleted * 100 / vindexstats.leafrows) >  
                       pmaxleafsdeleted)  
         THEN  
            vcount := vcount + 1;  
            DBMS_OUTPUT.PUT_LINE (  
               'Rebuilding index ' || vindexrec.index_owner||'.'|| vindexrec.index_name || '...');  

           <<alter_partitioned_index>>  
            BEGIN  
               EXECUTE IMMEDIATE  
                     'alter index '  
                  || vindexrec.index_owner||'.'  
                  || vindexrec.index_name  
                  || ' rebuild'  
                  || ' partition '  
                  || vindexrec.partition_name  
                  || ' parallel nologging compute statistics'  
                  || ' tablespace '  
                  || vindexrec.tablespace_name;  
            EXCEPTION  
               WHEN resource_busy OR TIMEOUT_ON_RESOURCE  
               THEN  
                  DBMS_OUTPUT.PUT_LINE (  
                     'alter partitioned index - busy and wait for 1 sec');  
                  DBMS_LOCK.sleep (c_trial_interval);  

                  IF trial <= c_max_trial  
                  THEN  
                     GOTO alter_partitioned_index;  
                  ELSE  
                     DBMS_OUTPUT.PUT_LINE (  
                           'alter partitioned index busy and waited - quit after '  
                        || TO_CHAR (c_max_trial)  
                        || ' trials');  
                     RAISE;  
                  END IF;  
               WHEN OTHERS  
               THEN  
                  DBMS_OUTPUT.PUT_LINE (  
                     'alter partitioned index err ' || SQLERRM);  
                  RAISE;  
            END;  
         END IF;  
      END IF;  

      CLOSE csrindexstats;  
   END LOOP;  

   DBMS_OUTPUT.PUT_LINE ('Local indices rebuilt: ' || TO_CHAR (vcount));  
END;  
/  
exit;  

3、输入日志样本
Current date and time is : Sun Apr 20 02:00:02 HKT 2014
Current DB is SYBO2 ===============================================
Rebuilding index GX_ADMIN.SYN_OUT_DATA_TBL_PK...
Rebuilding index GX_ADMIN.IDX_TDBK_SPLNK_PARENT_REF...
Rebuilding index GX_ADMIN.IDX_TDBK_SPLNK_CHILD_REF...
Rebuilding index GX_ADMIN.PK_TRADE_BROKER_TBL...
Rebuilding index GX_ADMIN.IDX_TDBK_INPUT_DATE...
    ................

4、后记
a、如果同一台服务器上有多个实例,且每个实例有相同的schema,此脚本会轮巡所有实例并根据analyze结果来rebuild。
a、大家应根据需要作相应调整,如脚本的路径信息等。
b、需要修改相应的schema name。
d、可根据系统环境调整相应的并行度。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-18175-1-1.html 上篇帖子: Oracle DG故障诊断一则:alter database recover to logical standby new_l... 下篇帖子: ORACLE数据库测试数据插入速度 Oracle
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表