[转载]oracle重建索引

原文地址:oracle重建索引作者:minnie

一:考虑重建索引的场合
1:表上频繁发生update,delete操作
2:表上发生了alter table ..move操作(move操作导致了rowid变化)


二:判断重建索引的标准
  索引重建是否有必要,一般看索引是否倾斜的严重,是否浪费了空间;
  那应该如何才可以判断索引是否倾斜的严重,是否浪费了空间,如下:
1,        对索引进行结构分析
Analyze index indexname validate structure;
2, 在执行步骤1的session中查询index_stats表,不要到别的session去查询
   select height,DEL_LF_ROWS/LF_ROWS from index_stats;
3, 在步骤2查询出来的height>=4或者DEL_LF_ROWS/LF_ROWS>0.2的场合,该索引考虑重建;
Example:
   SQL> select count(*) from test_index;
         COUNT(*)
----------
                   2072327
SQL> analyze index pk_t_test validate structure;
Index analyzed
        SQL> select height,DEL_LF_ROWS/LF_ROWS from index_stats;
                     HEIGHT         DEL_LF_ROWS/LF_ROWS
---------- -------------------
                           0
SQL> delete from test_index where rownum<250000;
          249999 rows deleted
        SQL> select height,DEL_LF_ROWS/LF_ROWS from index_stats;
                    HEIGHT                 DEL_LF_ROWS/LF_ROWS
---------- -------------------
                                           0
        SQL> analyze index pk_t_test validate structure;
                Index analyzed
SQL> select height,DEL_LF_ROWS/LF_ROWS from index_stats;
                    HEIGHT                  DEL_LF_ROWS/LF_ROWS
---------- -------------------
                                          0.0777430939338362


三:重建索引的方式
    1:drop 原来的索引,然后再创建索引;
    2:alter index indexname rebuild (online);
    方式一:耗时间,无法在24*7环境中实现
    方式二:比较快,可以在24*7环境中实现
    建议使用方式二


四:alter index rebuid内部过程和注意点
    1:alter index rebuild 和alter index rebuild online的区别
(1)        扫描方式不同
Rebuild以index fast full scan(or table full scan)方式读取原索引中的数据来构建一个新的索引,有排序的操作; rebuild online 执行表扫描获取数据,有排序的操作;
Rebuild  方式 (index fast full scan  or  table full scan  取决于统计信息的cost)
Eg1:
SQL> explain plan for alter index idx_policy_id2 rebuild;
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------
| Id  | Operation               Name           | Rows  | Bytes | Cost  |
---------------------------------------------------------------------
 0 | ALTER INDEX STATEMENT                    999K|  4882K|  3219 |
 1 |  INDEX BUILD NON UNIQUE| IDX_POLICY_ID2                  |
 2 |   SORT CREATE INDEX                       999K|  4882K|       |
 3 |    INDEX FAST FULL SCAN | IDX_POLICY_ID2    999K|  4882K|       |
---------------------------------------------------------------------
Eg2:
SQL>  explain plan for alter index idx_policy_id rebuild;
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------
| Id  | Operation               Name          | Rows  | Bytes | Cost  |
---------------------------------------------------------------------
 0 | ALTER INDEX STATEMENT                 2072K|     9M|   461 |
 1 |  INDEX BUILD NON UNIQUE| IDX_POLICY_ID                  |
 2 |   SORT CREATE INDEX                  2072K|     9M|       |
 3 |    TABLE ACCESS FULL   | TEST_INDEX      2072K|     9M|   461 |


Eg3: (注意和Eg1比较)
Rebuil online 方式:
SQL> explain plan for alter index idx_policy_id2 rebuild online;
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------
| Id  | Operation               Name           | Rows  | Bytes | Cost  |
---------------------------------------------------------------------|   0 | ALTER INDEX STATEMENT                    999K|  4882K|  3219 |
 1 |  INDEX BUILD NON UNIQUE| IDX_POLICY_ID2                  |
 2 |   SORT CREATE INDEX                     999K|  4882K|       |
 3 |    TABLE ACCESS FULL   | TEST_INDEX2       999K|  4882K|  3219 |
(2)        rebuild 会阻塞dml操作,rebuil online 不会阻塞dml操作;
(3)        rebuild online时系统会产生一个SYS_JOURNAL_xxx的IOT类型的系统临时日志表,所有rebuild online时索引的变化都记录在这个表中,当新的索引创建完成后,把这个表的记录维护到新的索引中去,然后drop掉旧的索引,rebuild online就完成了。

注意点:
1,        执行rebuild操作时,需要检查表空间是否足够;
2,        虽然说rebuild online操作允许dml操作,但是还是建议在业务不繁忙时间段进行;
3,        Rebuild操作会产生大量redo log ;

五:重建分区表上的分区索引
   1:重建分区索引方法:
     Alter index indexname rebuild partition paritionname tablespace tablespacename;
     Alter index indexname rebuild subpartition partitioname tablespace tablespacename;
     Partition name 可以从user_ind_partitions查找
     Tablepace 参数允许alter index操作更改索引的存储空间;

 

六:索引状态描述

在数据字典中查看索引状态,发现有三种:   
  VALID   
  N/A   
  UNUSABLE   

valid:当前索引有效
N/A :分区索引有效
unusable:索引失效

 

七:术语

  高基数:简单理解就是表中列的不同值多
  低基数:建单理解就是表中的列的不同值少
  以删除的叶节点数量:指得是数据行的delete操作从逻辑上删除的索引节点的数量,要记住oracle在删除数据行后,将“死“节点保留在索引中,这样做可以加快sql删除操作的速度,因此oracle删除数据行后可以不必重新平衡索引。
   索引高度:索引高度是指由于数据行的插入操作而产生的索引层数,当表中添加大量数据时,oracle将生成索引的新层次以适应加入的数据行,因此,oracle索引可能有4层,但是这只会出现在索引数中产生大量插入操作的区域。Oracle索引的三层结构可以支持数百万的项目,而具备4层或是更多层的需要重建。
    每次索引访问的读取数:是指利用索引读取一数据行时所需要的逻辑I/O操作数,逻辑读取不必是物理读取,因为索引的许多内容已经保存在数据缓冲区,然而,任何数据大于10的索引都需要重建。

    那么什么时候重建呢?我们可以利用analyze index …….. compute statistics 对表进行分析。然后察看dba_indexes中的blevel。这列是说明索引从根块到叶快的级别,或是深度。如果级别大于等于4。则需要重建,如下:
Select index_name,blevel from dba_indexes where blevel>=4.
   另一个从重建中受益的指标显然是当该索引中的被删除项占总的项数的百分比。如果在20%以上时,也应当重建,如下
SQL>anlyze index ------ validate structure
SQL>select (del_lf_rows_len/lf_rows_len)*100 from index_stats where name=’------‘
就能看到是否这个索引被删除的百分比。
上面只是判断,那么,怎样重建会更好呢?
建索引的办法:
a.        删除并从头开始建立索引。
b.        使用alter index -------- rebuild 命令重建索引
c.        使用alter index -------- coalesce命令重建索引。
下面讨论一下这三种方法的优缺点:
1).删除并从头开始建索引:方法是最慢的,最耗时的。一般不建议。
2).Alter index ---- rebuild 快速重建索引的一种有效的办法,因为使用现有索引项来重建新索引,如果客户操作时有其他用户在对这个表操作,尽量使用带online参数来最大限度的减少索引重建时将会出现的任何加锁问题,alter index ------- rebuild online.但是,由于新旧索引在建立时同时存在,因此,使用这种技巧则需要有额外的磁盘空间可临时使用,当索引建完后把老索引删除,如果没有成功,也不会影响原来的索引。利用这种办法可以用来将一个索引以到新的表空间。
Alter index ------ rebuild  tablespace -----。
  这个命令的执行步骤如下:
   首先,逐一读取现有索引,以获取索引的关键字。
   其次,按新的结构填写临时数据段。
   最后,一旦操作成功,删除原有索引树,降临时数据段重命名为新的索引。
   需要注意的是alter index ---rebuild 命令中必须使用tablespace字句,以保证重建工作是在现有索引相同的表空间进行。
3).alter index ----- coalesce 使用带有coalesce参数时重建期间不需要额外空间,它只是在重建索引时将处于同一个索引分支内的叶块拼合起来,这最大限度的减少了与查询过程中相关的潜在的加锁问题,但是,coalesce选项不能用来讲一个索引转移到其他表空间。

八:其他
   1:truncate 分区操作和truncate 普通表的区别
      Truncate 分区操作会导致全局索引失效; truncate 普通表对索引没有影响;
      Truncate 分区操作不会释放全局索引中的空间,而truncate 普通表会释放索引所占空间;
   2:rename 表名操作对索引没有影响,因为rename操作只是更改了数据字典,表中数据行的rowid并没有发生变化

posted @ 2015-01-27 11:29  刘竹青  阅读(210)  评论(0编辑  收藏  举报