ORACLE不可见索引(Invisible Indexes)

不可见索引概念

不可见索引(Invisible Index)是ORACLE 11g引入的新特性。不可见索引是会被优化器忽略的不可见索引,除非在会话或系统级别上将OPTIMIZER_USE_INVISIBLE_INDEXES初始化参数显式设置为TRUE。此参数的默认值是FALSE。如果是虚拟索引是为了合理、科学新增索引而设计的,那么不可见索引就是为了合理、科学的删除索引而设计的。为什么这样说呢? 因为DBA在维护索引时,我们经常会找出无用或低效的索引,并删除这些索引,在生产环境下,删除索引还是有一定风险的,即使ORACLE提供了监控索引使用情况的技术。例如,某些索引可能只是在一些周期的作业中被使用到,而如果监控周期没有覆盖到这些作业的触发点,就会认为索引是无用的而被删除。当作业启动后,可能就会对系统性能造成冲击。这时,可能就会手忙脚乱的去找回索引定义语句、重建索引。11G之前,我们可以先不删除索引,而将其修改为unusable。这样的话,索引的定义并未删除,只是索引不能再被使用也不会随着表数据的更新而更新。当需要重新使用该索引时,需要用rebuild语句重建、然后更新统计信息。对于一些大表来说,这个时间可能就非常长。在ORACLE 11g里提供了一个新的特性来降低直接删除索引或者禁用索引的风险,那就是索引不可见(Index Invisible)。我们可以将无用或低效的索引设置为不可见索引,当观察一段时间后,发现其对系统性能并无任何影响,那么就可以彻底删除索引了。

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

Using invisible indexes, you can do the following:

1.Test the removal of an index before dropping it.

2.Use temporary index structures for certain operations or modules of an application without affecting the overall application.

Unlike unusable indexes, an invisible index is maintained during DML statements.

不可见索引测试

创建测试表TEST,在表上新建不可见索引IDX_TEST_ID,不可见索引可以从字段VISIBILITY这个字段来区别,如下所示:

SQL> create table test
  2  as

  3  select * from dba_objects;

 

Table created.

 

SQL> create index idx_test_id on test(object_id) invisible;

 

Index created.

 

SQL> select index_name, status,visibility from dba_indexes where index_name=upper(‘idx_test_id‘);

 

INDEX_NAME                     STATUS   VISIBILIT

------------------------------ -------- ---------

IDX_TEST_ID                    VALID    INVISIBLE

 

 

 

SQL> show parameter optimizer_use_invisible_indexes;

 

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

optimizer_use_invisible_indexes      boolean     FALSE

SQL>                                                                                    

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME =>USER,TABNAME=>‘TEST‘,CASCADE => TRUE);

 

PL/SQL procedure successfully completed.

如下所示,优化器是“看不见”这个索引的,即使使用提示hint强制其走这个索引。优化器还是不会走索引扫描

SQL> set autotrace traceonly;
SQL> select * from test where object_id=12;

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 1357081020

 

--------------------------------------------------------------------------

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |     1 |    97 |   282   (1)| 00:00:04 |

|*  1 |  TABLE ACCESS FULL| TEST |     1 |    97 |   282   (1)| 00:00:04 |

--------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   1 - filter("OBJECT_ID"=12)

 

 

Statistics

----------------------------------------------------------

        424  recursive calls

          0  db block gets

       1094  consistent gets

          0  physical reads

          0  redo size

       1604  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          4  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

 

 

SQL> select /*+ index(text, idx_test_id) */ * from test where object_id=12;

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 1357081020

 

--------------------------------------------------------------------------

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |     1 |    97 |   282   (1)| 00:00:04 |

|*  1 |  TABLE ACCESS FULL| TEST |     1 |    97 |   282   (1)| 00:00:04 |

--------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   1 - filter("OBJECT_ID"=12)

 

 

Statistics

----------------------------------------------------------

          1  recursive calls

          0  db block gets

       1036  consistent gets

          0  physical reads

          0  redo size

       1604  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

设置参数optimizer_use_invisible_indexes为true后,此时优化器就会走索引范围扫描了。

SQL> alter session set optimizer_use_invisible_indexes=true;
 

Session altered.

 

SQL> select * from test where object_id=12;

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 1345973065

 

-------------------------------------------------------------------------------------------

| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT            |             |     1 |    97 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| TEST        |     1 |    97 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | IDX_TEST_ID |     1 |       |     1   (0)| 00:00:01 |

-------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - access("OBJECT_ID"=12)

 

 

Statistics

----------------------------------------------------------

          0  recursive calls

          0  db block gets

          4  consistent gets

          0  physical reads

          0  redo size

       1607  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

早期版本中,不可见索引有一些Bug,下面整理了一些这方面的Bug,应用相关的补丁或最新的版本都可避免碰到这些Bug。

1:使用DBMS_METADATA.GET_DDL获取不可见索引的定义不正确,少了关键字invisible

 

详情参考:DBMS_METADATA.GET_DDL Returns Incorrect DDL For Invisible Index (文档 ID 1965563.1)

 

 

2:Bug 9336476 - Optimizer 10053 trace shows wrong status for INVISIBLE index(文档 ID 9336476.8)

 

3:Bug 16544878 - Drop invisible index affects SQL execution plan (文档 ID 16544878.8)

 

4:Wrong Result With Invisible Index (文档 ID 1266380.1)


 

 

UPDATE statement fails with below error when all indexes are marked invisible.

ORA-14406: updated partition key is beyond highest legal partition key

The execution plan of the UPDATE is parallel plan.

 

5: Bug 9347681 - OERI [12863] with invisible indexing(文档 ID 9347681.8)

参考资料

http://blog.itpub.net/26736162/viewspace-2124044

时间: 2024-11-08 00:20:31

ORACLE不可见索引(Invisible Indexes)的相关文章

Oracle 11g新特性invisible index(不可见的索引)

如果一张表上有十几个索引,你有什么感受?显然会拖慢增.删.改的速度,不要指望开发人员能建好索引.我的处理方法是先监控很长的一段时间,看哪些索引没有用到,然后删除.但删除以后,如果发现某一天有用,那又要重新建,如果是大表,那就有些麻烦.现在11g提供一个新特性,不可见索引,可以建索引设置为不可见索引,CBO在评估执行计划的时候会忽略它,如果需要的时候,设置回来即可. 还有一种用途,你在调试一条SQL语句,要建一个索引测试,而你不想影响其他的会话,用不可见索引正是时候. SQL> drop tabl

Oracle中组合索引的使用详解(转)

在Oracle中可以创建组合索引,即同时包含两个或两个以上列的索引.在组合索引的使用方面,Oracle有以下特点: 1. 当使用基于规则的优化器(RBO)时,只有当组合索引的前导列出现在SQL语句的where子句中时,才会使用到该索引: 2. 在使用Oracle9i之前的基于成本的优化器(CBO)时, 只有当组合索引的前导列出现在SQL语句的where子句中时,才可能会使用到该索引,这取决于优化器计算的使用索引的成本和使用全表扫描的成本,Oracle会自动选择成本低的访问路径(请见下面的测试1和

ORACLE Index Lookup索引访问路径总结

在ORACLE中,索引访问/查找(Index Lookup)路径有五种方式,分别为INDEX UNIQUE SCAN.INDEX RANGE SCAN.INDEX FULL SCAN.INDEX FAST FULL SCAN .INDEX SKIP SCAN.下面通过一些案例介绍.总结一下这五种索引访问路径.本文是总结这方面的知识点,所以文中一些地方参考.引用了参考资料中的部分内容.详细.具体资料可以参考官方资料Index Scans 索引唯一扫描(INDEX UNIQUE SCAN)   索引

Oracle中的索引

Oracle中的索引 在关系数据库中,索引是一种与表有关的数据库结构,它是除表以外的另一个重要模式对象.索引是建立在表的一列或多个列上的辅助对象,目的是提高表中数据的访问速度. 索引时表示数据的另一种方式,它提供的数据顺序不同于数据在磁盘上的物理存储顺序.它重新排列数据的物理位置,使其值为有序键值列表,每个键值是指向表行的指针,故其排列方式使其搜索变得更加有效. 如果表中定义了主键约束,而主键列上不存在索引,则Oracle自动创建一个. Oracle中常用的索引类型有:B树索引.反向键索引.位图

Oracle序列和索引

序列和索引 一.序列 1.序列的概念: 序列(Sequence)是用来生成连续的整数数据的对象.它常常用来作为主键的增长列,可以升序,也可以降序. 2.创建序列: 语法:创建序列                                              语法解析: CREATE SEQUENCE sequence_name [STRAT WITH num] START WITH:从某一个整数开始,升序默认为1,降序默认为-1. [INCREMENT BY increment] I

Oracle中的索引详解

Oracle中的索引概述 索引与表一样,也属于段(segment)的一种.里面存放了用户的数据,跟表一样需要占用磁盘空间.索引是一种允许直接访问数据表中某一数据行的树型结构,为了提高查询效率而引入,是一个独立于表的对象,可以存放在与表不同的表空间中.索引记录中存有索引关键字和指向表中数据的指针(地址).对索引进行的I/O操作比对表进行操作要少很多.索引一旦被建立就将被Oracle系统自动维护,查询语句中不用指定使用哪个索引. 从物理上说,索引通常可以分为:分区和非分区索引.常规B树索引.位图(b

Oracle中B-TREE索引的深入理解(转载)

索引概述 索引与表一样,也属于段(segment)的一种.里面存放了用户的数据,跟表一样需要占用磁盘空间.只不过,在索引里的数据存放形式与表里的数据存放形式非常的不一样.在理解索引时,可以想象一本书,其中书的内容就相当于表里的数据,而书前面的目录就相当于该表的索引.同时,通常情况下,索引所占用的磁盘空间要比表要小的多,其主要作用是为了加快对数据的搜索速度,也可以用来保证数据的唯一性.但是,索引作为一种可选的数据结构,你可以选择为某个表里的创建索引,也可以不创建.这是因为一旦创建了索引,就意味着o

oracle之bitmap索引

oracle常见的索引是BTree索引和Bitmap索引. BTree索引特点: 默认索引 适合大量增删改查 不能用or操作符 适合高基数的列(即唯一值多) 创建sql:create index lie_idx1 on table(liename); Bitmap索引特点: 做update代价非常高 非常适合or操作符 基数少的列(即重复值多) 创建sql:create bitmap index lie_bit_idx1 on table(liename); Bitmap索引使用配注: 对列做位

查看oracle中表的索引

查看oracle中表的索引 oracle中表的索引信息存在 user_indexes 和 user_ind_columns 两张表里面,其中 user_indexes 系统视图存放是索引的名称以及该索引是否是唯一索引等信息, user_ind_columns 统视图存放的是索引名称,对应的表和列等 sql示例: select* from all_indexes where table_name='ACM_NETWORK_OPERATION'; select * from user_ind_col