您的位置:首页 > 数据库 > Oracle

ORACLE invisible index/virtual index(不可见/虚拟索引)

2012-09-13 19:28 579 查看
今天同事在优化的时候说到了虚拟索引这个东西,下面我们就来测试一下ORACLE数据的invisible与virtual索引,这两个索引对我们优化来说都有很大的好处。invisible索引在11G中才出现的,以前的版本中不可用。

invisible索引:当我们在生产环境中优化的时候,创建一个索引后,可能会影响到其它的SQL的执行效果,如果使用invisible索引,就不会影响到其它SQL语句的执行效果,因为它对其它是不可见,除非指定OPTIMIZER_USE_INVISIBLE_INDEXES这个参数为ture。invisible索引要占用空间,同时可以使用alter语句来对索引进行操作。

virtual索引:跟invisible一样,正常情况下不可用,除非指定_USE_NOSEGMENT_INDEXES参数为true。因为是虚拟的索引,所以创建他们不会分配空间,不能使用alter语句对它进行操作,可以对它进行分析。如果在一张几十G的表上创建一个virtual是很方面的。

下面就是关于invisible与virtual的测试。

测试环境是OS :RHEL 5.6 X*6_64 DB:11.2.0.3

1 invisible索引:

1.1 创建invisible索引,创建方法跟其它索引差不多,只是在最后增加invisible就可以了。
SQL> create index scott.pk_test_owner on scott.test(owner) invisible;

Index created.
1.2 执行测试语句
SQL> select count(*) from scott.test where owner='SCOTT';

COUNT(*)
----------
9
1.3 查看执行计划
这里就是select * from table(dbms_xplan.display_cursor(null,null,all))这个语句
SQL> @/home/oracle/rs/sql/plan.sql

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
SQL_ID  248pfx54z79v4, child number 0
-------------------------------------
select count(*) from scott.test where owner='SCOTT'

Plan hash value: 1950795681

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |       |       |   297 (100)|          |
|   1 |  SORT AGGREGATE    |      |     1 |    17 |            |          |
|*  2 |   TABLE ACCESS FULL| TEST |    12 |   204 |   297   (1)| 00:00:04 |
---------------------------------------------------------------------------
#这里我们看到了走的是全面扫描
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

1 - SEL$1
2 - SEL$1 / TEST@SEL$1

Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("OWNER"='SCOTT')

Column Projection Information (identified by operation id):
-----------------------------------------------------------

1 - (#keys=0) COUNT(*)[22]

Note
-----
- dynamic sampling used for this statement (level=2)

34 rows selected.
1.4 设置参数为true
SQL> alter session set OPTIMIZER_USE_INVISIBLE_INDEXES=true;

Session altered.

1.4 执行SQL
SQL> select count(*) from scott.test where owner='SCOTT';

COUNT(*)
----------
9
1.6 查看执行计划
SQL> @/home/oracle/rs/sql/plan

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
SQL_ID  248pfx54z79v4, child number 1
-------------------------------------
select count(*) from scott.test where owner='SCOTT'

Plan hash value: 4000037813

-----------------------------------------------------------------------------------
| Id  | Operation         | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |               |       |       |     1 (100)|          |
|   1 |  SORT AGGREGATE   |               |     1 |    17 |            |          |
|*  2 |   INDEX RANGE SCAN| PK_TEST_OWNER |     9 |   153 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------
#注意这里已经走的是index range scan扫描了,已经达到效果了
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

1 - SEL$1
2 - SEL$1 / TEST@SEL$1

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("OWNER"='SCOTT')

Column Projection Information (identified by operation id):
-----------------------------------------------------------

1 - (#keys=0) COUNT(*)[22]

Note
-----
- dynamic sampling used for this statement (level=2)

34 rows selected.

1.7 查看索引的类型
SQL> select index_name,visibility from dba_indexes where owner='SCOTT' and table_name='TEST';

INDEX_NAME                     VISIBILIT
------------------------------ ---------
PK_TEST_OWNER                  INVISIBLE
1.8 查看索引占用的空间大小
SQL> col segment_name for a20
SQL> select segment_name,sum(bytes/1024/1024)||'M' from dba_extents where segment_name='PK_TEST_OWNER'  group by segment_name;

SEGMENT_NAME         SUM(BYTES/1024/1024)||'M'
-------------------- -----------------------------------------
PK_TEST_OWNER        2M
1.9 重建索引
SQL> alter index scott.pk_test_owner rebuild;

Index altered.
SQL> select index_name,visibility from dba_indexes where owner='SCOTT' and table_name='TEST';

INDEX_NAME                     VISIBILIT
------------------------------ ---------
PK_TEST_OWNER                  INVISIBLE
1.10 invisible/visible转化
我们可以通过alter语句把对invisible/visible进行相互的转换
SQL> alter index scott.pk_test_owner visible;

Index altered.

SQL> select index_name,visibility from dba_indexes where owner='SCOTT' and table_name='TEST';

INDEX_NAME                     VISIBILIT
------------------------------ ---------
PK_TEST_OWNER                  VISIBLE

2 virtual索引
2.1 创建一个virutal索引,就是在普通创建索引的方法后面增加一个nosegment就可以。
SQL> create index scott.pk_test_objectname on scott.test(object_name) nosegment;

Index created.
2.2 执行测试语句,并查看执行计划
SQL> select count(*) from scott.test where object_name='TEST';

Execution Plan
----------------------------------------------------------
Plan hash value: 1950795681

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |    66 |   297   (1)| 00:00:04 |
|   1 |  SORT AGGREGATE    |      |     1 |    66 |            |          |
|*  2 |   TABLE ACCESS FULL| TEST |    12 |   792 |   297   (1)| 00:00:04 |
---------------------------------------------------------------------------
#注意这里走的全表扫描
Predicate Information (identified by operation id):
---------------------------------------------------

2 - filter("OBJECT_NAME"='TEST')

Note
-----
- dynamic sampling used for this statement (level=2)

Statistics
----------------------------------------------------------
5  recursive calls
0  db block gets
1134  consistent gets
1061  physical reads
0  redo size
526  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
2.3 设置参数为true
SQL>  alter session set "_USE_NOSEGMENT_INDEXES" = true;

Session altered.
2.4 执行测试语句,并查看执行计划
SQL> select count(*) from scott.test where object_name='TEST';

Execution Plan
----------------------------------------------------------
Plan hash value: 2753868186

----------------------------------------------------------------------------------------
| Id  | Operation         | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                    |     1 |    66 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |                    |     1 |    66 |            |          |
|*  2 |   INDEX RANGE SCAN| PK_TEST_OBJECTNAME |    12 |   792 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
#已经走了索引了,达到了效果
Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("OBJECT_NAME"='TEST')

Note
-----
- dynamic sampling used for this statement (level=2)

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
1064  consistent gets
1061  physical reads
0  redo size
526  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
SQL> select table_name,index_name from dba_indexes where owner='SCOTT' and table_name='TEST';

TABLE_NAME                     INDEX_NAME
------------------------------ ------------------------------
TEST                           PK_TEST_OWNER
2.5 查看索引是否分配了segment,这里为0,所以没有分配segment,不占用空间的。
SQL> select count(*) from dba_segments where segment_name='PK_TEST_OBJECTNAME';

COUNT(*)
----------
0
2.6 测试是否可以用alter对index进行操作
SQL> alter index PK_TEST_OBJECTNAME rebuild;
alter index PK_TEST_OBJECTNAME rebuild
*
ERROR at line 1:
ORA-01418: specified index does not exist

invisible/virtual索引就测试到这里。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ORACLE invisible vir