Oracle 重建索引脚本

该指数是一个有力的武器,以提高数据库的查询性能。

没有索引,喜欢同样的标签库没有书籍,找书,他们想预订比登天还难。中,尤其是在批量的DML的情形下会产生对应的碎片。以及B树高度会发生对应变化。因此能够对这些变化较大的索引进行重构以提高性能。N久曾经Oracle建议我们定期重建那些高度为4。已删除的索引条目至少占有现有索引条目总数的20%的这些表上的索引。但Oracle如今强烈建议不要定期重建索引。

详细能够參考文章:Oracle 重建索引的必要性

虽然如此重建索引还是有必要的。仅仅是不建议定期。本文给出了重建索引的脚本供大家參考。

1、重建索引shell脚本

[email protected]:~/dba_scripts/custom/bin> more rebuild_unbalanced_indices.sh
# +-------------------------------------------------------+
# +    Rebulid unblanced indices                          |
# +    Author : Leshami                                   |
# +    Parameter : No                                     |
# +    Blog : http://blog.csdn.net/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
[email protected]

# ------------------------------------
# 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脚本

[email protected]:~/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、假设同一台server上有多个实例,且每一个实例有同样的schema。此脚本会轮巡全部实例并依据analyze结果来rebuild。 
a、大家应依据须要作对应调整。如脚本的路径信息等。

b、须要改动对应的schema name。

d、可依据系统环境调整对应的并行度。

5、相关參考
    Oracle 聚簇因子(Clustering factor) 
    Oracle 索引监控(monitor index)
    Oracle 索引监控与外键索引 
    收集统计信息导致索引被监控 
    Oracle 监控索引的使用率
    NULL 值与索引(一)
    NULL 值与索引(二)
    函数使得索引列失效

Oracle 索引质量分析

Oracle 重建索引的必要性

版权声明:本文博主原创文章,博客,未经同意不得转载。

时间: 2024-10-14 22:15:37

Oracle 重建索引脚本的相关文章

[转]Oracle 重建索引的必要性

http://blog.csdn.net/leshami/article/details/23763963 索引重建是一个争论不休被不断热烈讨论的议题.当然Oracle官方也有自己的观点,我们很多DBA也是遵循这一准则来重建索引,那就是Oracle建议对于索引深度超过4级以及已删除的索引条目至少占有现有索引条目总数的20% 这2种情形下需要重建索引.近来Oracle也提出了一些与之相反的观点,就是强烈建议不要定期重建索引.本文是参考了1525787.1并进行相应描述. 1.重建索引的理由 a.O

ORACLE关于索引是否需要定期重建争论的整理

ORACLE数据库中的索引到底要不要定期重建呢? 如果不需要定期重建,那么理由是什么? 如果需要定期重建,那么理由又是什么?另外,如果需要定期重建,那么满足那些条件的索引才需要重建呢?关于这个问题,网上也有很多争论,也一直让我有点困惑,因为总有点不得庐山真面目的感觉,直到上周看到了一些资料,遂整理于此,方便以后翻阅: 首先来看看网上关于索引需要重建的原因或标准: 一:分析(analyze)指定索引之后,查询index_stats的height字段的值,如果这个值>=4 ,最好重建(rebuild

Oracle性能分析9:重建索引

当索引出现问题时,会导致严重的性能问题,索引问题包括索引不可用.索引碎片导致性能下降,我们需要一些手段在检测索引的问题,并解决这些问题.这一篇将为你讲述怎么定位索引问题,并提供了解决的办法. 索引不可用 索引不可用的原因有很多,包括: 1)索引空间耗尽,导致SQL*Loader更新索引失败: 2)创建索引的过程中实例失败: 3)唯一键有重复值: 4)某个索引的顺序与sorted indexes子句中指定的顺序不同: 5)移动表或表分区(alter table move和alter table m

Oracle性能分析10:重建索引续-常用SQL

上一节讲了重建索引的原因和重建方法,这节继续介绍几个常用的SQL语句和存储过程. 查询所有失效的全局索引 select index_name, status from user_indexes where table_name = upper(table_name) and status = 'UNUSABLE' 查询所有失效的分区索引 select index_name, status from user_ind_partitions where index_name in (select i

Oracle之索引(Index)实例讲解 - 基础

Oracle之索引(Index)实例讲解 - 基础 索引(Index)是关系数据库中用于存放表中每一条记录位置的一种对象,主要目的是加快数据的读取速度和数据的完整性检查.索引的建立是一项技术性要求非常高的工作. 一般在数据库设计阶段就要考虑到如何设计和创建索引. 1. 创建索引 创建索引的语法: CREATE [UNIQUE] INDEX [schema.] index ON [schema.] table (column [ASC | DESC], column [ASC | DESC]...

Oracle 重建表(rename)注意事项总结

一.概述 前一段时间,有一个DBA朋友在完成重建表(rename)工作后,第二天早上业务无法正常运行,出现数据无法插入的限制和错误,后来分析才发现,错误的原因是使用rename方式重建表以后,其它引用这个表的外键约束指向没有重新定义到这个重建的新表中,从而导致这些表在插入新数据时,违反数据完整性约束,导致数据无法正常插入.影响了业务大概有1个多小时,真是一次血淋淋的教训啊. 使用rename方式重建表是我们日常DBA维护工作中经常使用的一种方法,因为CTAS+rename这种配合方式,非常实用和

Oracle 分区索引

分区索引(或索引分区)主要是针对分区表而言的.随着数据量的不断增长,普通的堆表需要转换到分区表,其索引呢,则对应的转换到分区索引.分区索引的好处是显而易见的.就是简单地把一个索引分成多个片断,在获取所需数据时,只需要访问更小的索引片断(块)即可实现.同时把分区放在不同的表空间可以提高分区的可用性和可靠性.本文主要描述了分区索引的相关特性并给出演示示例. 1.分区索引的相关概念a.分区索引的几种方式:表被分区而索引未被分区:表未被分区,而索引被分区:表和索引都被分区b.分区索引可以分为本地分区索引

对比:重建索引与更新统计

最近经常被问到的一个问题是关于在数据库维护过程,重建索引与更新统计的执行先后次序.通常,需要考虑以下几点,这里注意的是有两种统计:索引统计.列统计. 1)默认情况下,UPDATE STATISTICS 将会更新索引统计和列统计,如果语句中仅使用了COLUMNS选项,则只更新列统计,若仅使用了INDEX选项,则只更新索引统计 2)默认情况下,UPDATE STATISTICS语句仅采样表的一部分数据,使用UPDATE STATISTICS WITH FULLSCAN则会扫描全表 3)重建索引(如使

移动表到新表空间后重建索引

将某个表空间内的多个数据库表移动到另一个表空间后,由于没有处理索引,导致到新库中查询.插入等操作时,oracle报错: ORA-01502: 索引 'WWYSBI41.SYS_C0027004' 或这类索引的分区处于不可用状态 原因是仍用了之前表空间的索引,解决办法是重建这些索引. 对单个表索引, alter index <index_name> rebuild (online) 注:上面的index_name外面的<和>只是表示这是一个变量,并不是真的要加<与>. 对