12
返回列表 发新帖
楼主: marvinzzy

[笔记] 关于REBUILD 大量INDEX问题

[复制链接]
论坛徽章:
3
ITPUB元老
日期:2005-02-28 12:57:00授权会员
日期:2005-10-30 17:05:33会员2006贡献徽章
日期:2006-04-17 13:46:34
11#
发表于 2005-3-11 10:20 | 只看该作者
希望这个脚本有用,不过如果索引很多很大,执行的时间很长!

This script determines whether an index is a good candidate for a rebuild or for
a bitmap index.  All indexes for a given schema or for a subset of schema's are
analyzed (except indexes under SYS and SYSTEM)

REM =============================================================
REM
REM                         rebuild_indx.sql
REM
REM  Copyright (c) Oracle Software, 1998 - 2000
REM
REM  Author  : Jurgen Schelfhout
REM
REM  The sample program in this article is provided for educational
REM  purposes only and is NOT supported by Oracle Support Services.
REM  It has been tested internally, however, and works as documented.
REM  We do not guarantee that it will work for you, so be sure to test
REM  it in your environment before relying on it.
REM
REM  This script will analyze all the indexes for a given schema
REM  or for a subset of schema's. After this the dynamic view
REM  index_stats is consulted to see if an index is a good
REM  candidate for a rebuild or for a bitmap index.
REM
REM  Database Version : 7.3.X and above.
REM
REM =============================================================

prompt
ACCEPT spoolfile CHAR prompt 'Output-file : ';
ACCEPT schema CHAR prompt 'Schema name (% allowed) : ';
prompt
prompt
prompt Rebuild the index when :
prompt   - deleted entries represent 20% or more of the current entries
prompt   - the index depth is more then 4 levels.
prompt Possible candidate for bitmap index :
prompt   - when distinctiveness is more than 99%
prompt
spool &spoolfile

set serveroutput on
set verify off
declare
c_name        INTEGER;
ignore        INTEGER;
height        index_stats.height%TYPE := 0;
lf_rows       index_stats.lf_rows%TYPE := 0;
del_lf_rows   index_stats.del_lf_rows%TYPE := 0;
distinct_keys index_stats.distinct_keys%TYPE := 0;
cursor c_indx is
  select owner, table_name, index_name
  from dba_indexes
  where owner like upper('&schema')
    and owner not in ('SYS','SYSTEM');
begin
dbms_output.enable (1000000);
dbms_output.put_line ('Owner           Index Name                              % Deleted Entries Blevel Distinctiveness');
dbms_output.put_line ('--------------- --------------------------------------- ----------------- ------ ---------------');

c_name := DBMS_SQL.OPEN_CURSOR;
for r_indx in c_indx loop
  DBMS_SQL.PARSE(c_name,'analyze index ' || r_indx.owner || '.' ||
                 r_indx.index_name || ' validate structure',DBMS_SQL.NATIVE);
  ignore := DBMS_SQL.EXECUTE(c_name);

  select HEIGHT, decode (LF_ROWS,0,1,LF_ROWS), DEL_LF_ROWS,
         decode (DISTINCT_KEYS,0,1,DISTINCT_KEYS)
         into height, lf_rows, del_lf_rows, distinct_keys
  from index_stats;
--
-- Index is considered as candidate for rebuild when :
--   - when deleted entries represent 20% or more of the current entries
--   - when the index depth is more then 4 levels.(height starts counting from 1 so > 5)
-- Index is (possible) candidate for a bitmap index when :
--   - distinctiveness is more than 99%
--
  if ( height > 5 ) OR ( (del_lf_rows/lf_rows) > 0.2 ) then
    dbms_output.put_line (rpad(r_indx.owner,16,' ') || rpad(r_indx.index_name,40,' ') ||
                          lpad(round((del_lf_rows/lf_rows)*100,3),17,' ') ||
                          lpad(height-1,7,' ') || lpad(round((lf_rows-distinct_keys)*100/lf_rows,3),16,' '));
  end if;

end loop;
DBMS_SQL.CLOSE_CURSOR(c_name);
end;
/

spool off
set verify on

使用道具 举报

回复
论坛徽章:
0
12#
发表于 2005-3-11 10:21 | 只看该作者
最初由 baikejia 发布
[B]如果表很大,要做很久。
上班的时候做,会导致别人无法使用那个索引,影响很大的。
还是下班做吧 [/B]


使用online参数重建索引,不影响其他用户使用吧?就是对空间需求大些,
惭愧不知道啥版本以上才有,不过8i上就有了

使用道具 举报

回复
论坛徽章:
86
2015中国数据库技术大会纪念徽章
日期:2015-04-24 16:04:24马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11优秀写手
日期:2013-12-18 09:29:11日产
日期:2013-10-17 08:44:39马自达
日期:2013-08-26 16:28:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-23 16:55:51马上有房
日期:2014-02-19 11:55:14
13#
发表于 2005-3-11 11:46 | 只看该作者
在给你个过程,首先去判断碎片率,如果大于2再进行重建。支持分区及子分区。

create or replace procedure CHECK_INDEX is
  percent                       number;               --碎片率
  chained                       number;               --碎片
  indxname                      varchar2(100);        --索引名称
  partname                      varchar2(100);        --partition_name
  segtype                       varchar2(100);        --segment_type
  tablespace                    varchar2(100);        --表空间
  
  cursor cSele_indx is
    select t.index_name,t.tablespace_name
      from user_indexes t
     where t.temporary='N';
  
  cursor cSele_seg is
    select t.partition_name,t.segment_type,t.tablespace_name
      from dba_segments t
     where t.segment_name=indxname;
begin
  open cSele_indx;
  fetch cSele_indx into indxname,tablespace;
  
  while cSele_indx%found loop
    execute immediate 'analyze index '||indxname||' validate structure';  --进行分析
   
    select count(*)
      into chained
      from index_stats t
     where t.lf_rows_len>0;
   
    if chained>0 then                                                     
      select Round((t.del_lf_rows_len/t.lf_rows_len)*100,2)
        into percent                                                      --检查碎片率
        from index_stats t
       where t.lf_rows_len>0;
    end if;
   
    if percent>2 then                                                     --如碎片率大于2%时进行索引重建
                                                                          --可以根据实际情况对这个比率进行修改
      dbms_output.put_line(indxname||':'||to_char(percent));
            
      open cSele_seg;
      fetch cSele_seg into partname,segtype,tablespace;
      while cSele_seg%found loop
        if segtype='INDEX' then                                           --未分区索引
          execute immediate 'alter index '||indxname||' rebuild tablespace '||tablespace||' nologging';
        end if;
        if segtype='INDEX PARTITION' then                                 --分区索引
          execute immediate 'alter index '||indxname||' rebuild partition '||partname||' tablespace '||tablespace||' parallel (degree 4)';
        end if;
        if segtype='INDEX SUBPARTITION' then                              --组合分区索引
          execute immediate 'alter index '||indxname||' rebuild subpartition '||partname||' tablespace '||tablespace||' parallel (degree 4)';
        end if;
        
        fetch cSele_seg into partname,segtype,tablespace;
      end loop;
      
      close cSele_seg;
    end if;
   
    fetch cSele_indx into indxname,tablespace;
  end loop;
  
  close cSele_indx;

end CHECK_INDEX;

使用道具 举报

回复
论坛徽章:
5
ITPUB元老
日期:2005-03-15 09:15:43ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44凯迪拉克
日期:2013-12-27 09:30:49
14#
发表于 2005-3-11 13:03 | 只看该作者
最初由 胡一刀 发布
[B]

使用online参数重建索引,不影响其他用户使用吧?就是对空间需求大些,
惭愧不知道啥版本以上才有,不过8i上就有了 [/B]



使用online参数重建,会慢很多的。
最可怕的是,如果你的重建索引的sql被杀掉了,那么你只能重启数据库了。你要是想重建的话,会报告说“正在重建”。这个oracle的一个bug

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表