HelloDBA [English]
搜索Internet 搜索 HelloDBABA
  Oracle技术站。email: fuyuncat@gmail.com  MSN: fuyuncat@hotmail.com   acoug  acoug 

11g新特性 —— 索引不可见(Index Invisible)

[English]

作者: fuyuncat

来源: www.HelloDBA.com

日期: 2009-08-26 06:42:40

分享到  新浪微博 腾讯微博 人人网 i贴吧 开心网 豆瓣 淘宝 推特 Facebook GMail Blogger Orkut Google Bookmarks

    索引维护是DBA的一项重要工作。当一个系统运行很长一段时间,经过需求变更、结构设计变化后,系统中就可能会存在一些不会被使用的索引,或者使用效率很低的索引。这些索引的存在,不仅占用系统空间,而且会降低事务效率,增加系统的waits。因此,我们需要找出那些无用或低效索引的索引并删除它们(找出无用索引可以通过索引监控的方法)。

    但是,直接删除索引还是存在一定风险的。例如,某些索引可能只是在一些周期的作业中被使用到,而如果监控周期没有覆盖到这些作业的触发点,就会认为索引是无用的而被删除。当作业启动后,可能就会对系统性能造成冲击。这时,可能就会手忙脚乱的去找回索引定义语句、重建索引。

    11g之前,我们可以先不删除索引,而将其修改为unusable。这样的话,索引的定义并未删除,只是索引不能再被使用也不会随着表数据的更新而更新。当需要重新使用该索引时,需要用rebuild语句重建、然后更新统计信息。对于一些大表来说,这个时间可能就非常长。

    在11g里,oracle提供了一个新的特性来降低直接删除索引或者禁用索引的风险,那就是索引不可见(Index Invisible)。我们可以在创建索引时指定invisible属性或者用alter语句来修改索引为invisible

SQL代码
  1. SQL> create index t_test1_idx on t_test1(table_name) invisible;   
  2.   
  3. Index created.   
  4.   
  5. SQL> alter index t_test1_idx invisible;   
  6.   
  7. Index altered.  

    当索引被设为不可见后,实际上就是指该索引对于优化器不可见,而索引的正常更新并不受影响——即表在增、删、改时,索引也会被更新。只是当优化器在选择查询计划时会“无视”该索引(无论是CBO或RBO):

SQL代码
  1. SQL> create table t_test1 as select * from dba_tables;   
  2.   
  3. Table created.   
  4.   
  5. SQL> create index t_test1_idx on t_test1(table_name);   
  6.   
  7. Index created.   
  8.   
  9. SQL> analyze table t_test1 compute statistics for table for all indexes;   
  10.   
  11. Table analyzed.   
  12.   
  13. SQL> set autot trace exp   
  14.   
  15. SQL> select * from t_test1 where table_name like 'HR%';   
  16.   
  17. no rows selected   
  18.   
  19.   
  20. Execution Plan   
  21. ----------------------------------------------------------   
  22. Plan hash value: 3466041839   
  23.   
  24. -------------------------------------------------------------------------------------------   
  25. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |   
  26. -------------------------------------------------------------------------------------------   
  27. |   0 | SELECT STATEMENT            |             |   126 | 27468 |    14   (0)| 00:00:01 |   
  28. |   1 |  TABLE ACCESS BY INDEX ROWID| T_TEST1     |   126 | 27468 |    14   (0)| 00:00:01 |   
  29. |*  2 |   INDEX RANGE SCAN          | T_TEST1_IDX |    23 |       |     2   (0)| 00:00:01 |   
  30. -------------------------------------------------------------------------------------------   
  31.   
  32. Predicate Information (identified by operation id):   
  33. ---------------------------------------------------   
  34.   
  35.    2 - access("TABLE_NAME" LIKE 'HR%')   
  36.        filter("TABLE_NAME" LIKE 'HR%')   
  37.   
  38. SQL> alter index t_test1_idx invisible;   
  39.   
  40. Index altered.   
  41.   
  42. SQL> select * from t_test1 where table_name like 'HR%';   
  43.   
  44. no rows selected   
  45.   
  46.   
  47. Execution Plan   
  48. ----------------------------------------------------------   
  49. Plan hash value: 1883417357   
  50.   
  51. -----------------------------------------------------------------------------   
  52. | Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |   
  53. -----------------------------------------------------------------------------   
  54. |   0 | SELECT STATEMENT  |         |   126 | 27468 |    25   (0)| 00:00:01 |   
  55. |*  1 |  TABLE ACCESS FULL| T_TEST1 |   126 | 27468 |    25   (0)| 00:00:01 |   
  56. -----------------------------------------------------------------------------   
  57.   
  58. Predicate Information (identified by operation id):   
  59. ---------------------------------------------------   
  60.   
  61.    1 - filter("TABLE_NAME" LIKE 'HR%')   

    如果我们需要重新使该所有有效,只需要再将其改为visible就可以了——这个过程不是重建,仅仅是修改索引的一个属性,非常快!

SQL代码
  1. SQL> set timing on  
  2. SQL> alter index t_test1_idx visible;   
  3.   
  4. Index altered.   
  5.   
  6. Elapsed: 00:00:00.01  

    当然,当索引被设为不可见时,并非完全不可用。可以通过修改参数optimizer_use_invisible_indexestrue(默认为false,system级别和session级别都可以):

SQL代码
  1. SQL> select index_name, visibility from user_indexes where index_name='T_TEST1_IDX';   
  2.   
  3. INDEX_NAME                     VISIBILIT   
  4. ------------------------------ ---------   
  5. T_TEST1_IDX                    INVISIBLE   
  6.   
  7. SQL>   
  8.   
  9. SQL> alter session set optimizer_use_invisible_indexes=true;   
  10.   
  11. Session altered.   
  12.   
  13. SQL> set autot trace exp   
  14. SQL> select * from t_test1 where table_name like 'HR%';   
  15.   
  16. Execution Plan   
  17. ----------------------------------------------------------   
  18. Plan hash value: 3466041839   
  19.   
  20. -------------------------------------------------------------------------------------------   
  21. | Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |   
  22. -------------------------------------------------------------------------------------------   
  23. |   0 | SELECT STATEMENT            |             |   126 | 27468 |    14   (0)| 00:00:01 |   
  24. |   1 |  TABLE ACCESS BY INDEX ROWID| T_TEST1     |   126 | 27468 |    14   (0)| 00:00:01 |   
  25. |*  2 |   INDEX RANGE SCAN          | T_TEST1_IDX |    23 |       |     2   (0)| 00:00:01 |   
  26. -------------------------------------------------------------------------------------------   
  27.   
  28. Predicate Information (identified by operation id):   
  29. ---------------------------------------------------   
  30.   
  31.    2 - access("TABLE_NAME" LIKE 'HR%')   
  32.        filter("TABLE_NAME" LIKE 'HR%')  

    这里还需要指出一点,当索引不可见时,只能通过上面的参数使之在查询计划中可用,即使通过HINT也无法改变。

SQL代码
  1. SQL> select /*+ index(t_test1 T_TEST1_IDX) */ * from t_test1 t where table_name like 'HR%';   
  2. Elapsed: 00:00:00.00   
  3.   
  4. Execution Plan   
  5. ----------------------------------------------------------   
  6. Plan hash value: 1883417357   
  7.   
  8. -----------------------------------------------------------------------------   
  9. | Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |   
  10. -----------------------------------------------------------------------------   
  11. |   0 | SELECT STATEMENT  |         |   126 | 27468 |    25   (0)| 00:00:01 |   
  12. |*  1 |  TABLE ACCESS FULL| T_TEST1 |   126 | 27468 |    25   (0)| 00:00:01 |   
  13. -----------------------------------------------------------------------------   
  14.   
  15. Predicate Information (identified by operation id):   
  16. ---------------------------------------------------   
  17.   
  18.    1 - filter("TABLE_NAME" LIKE 'HR%')  

    在官方文档上对这一特性的说明中也只有提到该参数才起作用:

Beginning with Release 11g, you can create invisible indexes. An invisible index is an index that is ignored by the optimizer unless you explicitly set the OPTIMIZER_USE_INVISIBLE_INDEXES initialization parameter to TRUE at the session or system level.

--- The End ---

Top

Copyright ©2005,HelloDBA.Com 保留一切权利

申明
by fuyuncat