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

oracle虚拟索引的运用

2013-12-25 09:27 337 查看
   在实际的调优工作,将执行计划中的大表的全表扫描变为索引扫描是一个重要的手段,当为大表做调优的时候,难免会建索引试试看,这个不是很好。最好是建一个虚拟索引,看看CBO的评估,这种做法更高效一些。下面我们来做个试验,然后用10046探究下其原理。

SQL> drop table test purge;

SQL> create table test as select * from dba_objects;

SQL> alter session set events '10046 trace name context forever ,level 12' ;

SQL> create index ind_test_id on test(object_id) nosegment;

SQL> alter session set events '10046 trace name context off' ;

SQL> alter session set "_use_nosegment_indexes"=true;--要设置一个隐含的参数

SQL> create index ind_test_id on test(object_id) nosegment;--建立虚拟索引

--这个并不是真实的执行计划,而是plan_table中的计划


SQL> explain plan for select * from test where object_id=1;

SQL> set linesize 1000

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT

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

Plan hash value: 1064545891

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

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

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

|   0 | SELECT STATEMENT            |             |     8 |  1416 |     5   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| TEST        |     8 |  1416 |     5   (0)| 00:00:01 |

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

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

Predicate Information (identified by operation id):

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

   2 - access("OBJECT_ID"=1)

SQL> set autotrace traceonly

SQL> select * from test where object_id=1;

未选定行

执行计划

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

Plan hash value: 1064545891

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

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

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

|   0 | SELECT STATEMENT            |             |     8 |  1416 |     5   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| TEST        |     8 |  1416 |     5   (0)| 00:00:01 |

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

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

Predicate Information (identified by operation id):

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

   2 - access("OBJECT_ID"=1)

统计信息

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

          4  recursive calls

          0  db block gets

        772  consistent gets

        279  physical reads

          0  redo size

        992  bytes sent via SQL*Net to client

        374  bytes received via SQL*Net from client

          1  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          0  rows processed

SQL> set autotrace off
--以下看的是真实执行计划,从share_pool中获取的,显然是用不到索引。

SQL> alter session set statistics_level=all;

SQL> select * from test where object_id=1;

SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

PLAN_TABLE_OUTPUT

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

SQL_ID  btuhzhv88wwv3, child number 0

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

select * from test where object_id=1

Plan hash value: 1357081020

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

| Id  | Operation         | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |

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

|*  1 |  TABLE ACCESS FULL| TEST |      1 |      8 |      0 |00:00:00.01 |     706 |

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

Predicate Information (identified by operation id):

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

   1 - filter("OBJECT_ID"=1)

   

在user_indexes中找不到这个索引。

SQL> select index_name,status from user_indexes where table_name='TEST';

未选定行

      探究虚拟索引的原理,只是在数据字典中加了一个索引的记录,使得优化器能够意识到一个索引的存在,从而判断是否使用该索引作为访问路径。通过10046跟踪发现索引的信息插入到到数据字典中了。

SQL> alter session set events '10046 trace name context forever ,level 12' ;

SQL> create index ind_test_id on test(object_id) nosegment;

SQL> alter session set events '10046 trace name context off' ;

insert into obj$(owner#,name,namespace,obj#,type#,ctime,mtime,stime,status,

  remoteowner,linkname,subname,dataobj#,flags,oid$,spare1,spare2)

values

(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16, :17)

insert into icol$(obj#,bo#,intcol#,pos#,segcol#,segcollength,offset,col#,

  spare1,spare2)

values

(:1,:2,:3,:4,0,0,0,:5,:6,:7)

insert into ind$(bo#,obj#,ts#,file#,block#,intcols,type#,flags,property,

  pctfree$,initrans,maxtrans,blevel,leafcnt,distkey,lblkkey,dblkkey,clufac,

  cols,analyzetime,samplesize,dataobj#,degree,instances,rowcnt,pctthres$,

  indmethod#,trunccnt,spare1,spare4,spare2,spare6)

values

(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18,:19,:20,:21,

  :22,decode(:23,1,null,:23),decode(:24,1,null,:24),:25, :32*256+:26,:27,:28,

  :29,:30,:31,:33)

SQL> select o.obj#,o.owner#,o.name from obj$ o where name =upper('ind_test_id');

      OBJ#     OWNER# NAME

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

     61081         61 IND_TEST_ID
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: