oracle索引及分析

通过实验来说明oracle的数据库索引


实验1:
create table b0806 as select * from dba_objects;
create index ind_b0806 on b0806(object_id);
set autotrace traceonly;
select object_id from b0806 ;

实验结果:进行了全表扫描而没有走索引:
----------------------------------------------------------------------------
| Id  | Operation	  | Name   | Rows  | Bytes | Cost (%CPU)| Time	   |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	   | 82624 |  1048K|   338   (1)| 00:00:05 |
|   1 |  TABLE ACCESS FULL| B0806A | 82624 |  1048K|   338   (1)| 00:00:05 |
----------------------------------------------------------------------------

实验2
create table b0806a as select * from dba_objects;
alter table b0806a modify object_id not null;
create index ind_b0806a on b0806a(object_id);
set autotrace traceonly;
select object_id from b0806a;

实验2结果,走了索引
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |		  | 82624 |  1048K|    54   (0)| 00:00:0
1 |

|   1 |  INDEX FAST FULL SCAN| IND_B0806A | 82624 |  1048K|    54   (0)| 00:00:0
1 |
--------------------------------------------------------------------------------

总结:
实验1之所以没有走索引是因为object_id有可能为null,null值是不存在索引的B*Tree数中的,因此数据库知道如果走了索引,
索引,那么为NULL的行就娶不到了,结果是不对的;实验2之所以走了索引,是因为,查询的列定义为了not null,这意味着
索引中能获取到全部的数据结果。


实验3--------------------------------------------------
create table a0806z as select * from dba_objects;


create index ind_a0806z on a0806z(object_id,object_type);

alter table a0806z modify (object_id  not null);
alter table a0806z modify (object_type not null);

select object_id from a0806z ;--走索引

select object_type  from a0806z ;--走索引


select object_id,object_type from a0806z where DATA_OBJECT_ID=800;--全表扫描,因为索引中找不到DATA_OBJECT_ID



select object_id,object_type from a0806z where object_id=1000;--走索引

select object_id,object_type from a0806z where object_type='VIEW';--走索引

select object_id,object_type from a0806z where object_id=1000 and object_type='VIEW';--走索引


select object_id,object_type,object_name from a0806z where object_id=1000;--走索引,这里由于查询的列object_name不在
索引中,因此当数据库遍历获取查询结果时,会先到索引的B*Tree中找到object_id=1000的记录,我们都知道索引的叶子节点保存了索引
列的值的同时,也保存了索引所在行的rowid(该行数据的物理地址),每一行object_name值的获取都要进行回表操作,消耗的性能比较大
那么问题来了,上面这条语句为什么还走索引?因为object_id=1000的结果行数不多,在这种场景oracle通过计算,即使需要回表,也比全表
扫描性能好,因此选择走索引,但是下面这行语句就恰好相反object_type='VIEW'值多。

select object_id,object_type,object_name from a0806z where object_type='VIEW';--全表扫描

---------------------------------------------------------------------------------------------------------------------
唯一索引
create table testind1(id number);
create unique index  ind_testind1  on   testind1(id);

 insert into testind1 values(1);
 insert into testind1 values(1);--插入时报错,因为索引指定了唯一索引,所以早构建B*Tree的时候不能出现相同的索引
 insert into testind1 values(null);
 insert into testind1 values(null);--插入不报错,因为null值不存储在B*Tree树中,不存B*Tree那么 unique index就不作用在这类数据上



create table testind2(id number,name varchar2(20));
create unique index  ind_testind2  on   testind2(id,name);
 insert into testind2(id) values(1);
 
 insert into testind2(id) values(1);--不报错,因为定义的是组合索引,两个唯一才叫唯一
insert into testind2(id,name) values(1,'a');
insert into testind2(id,name) values(1,'b');

 insert into testind2 values(1,null);
insert into testind2 values(null,null);--不报错,null不存索引中


create table testind3(id number,name varchar2(20),local varchar2(20));
create unique index  ind_testind3  on   testind3(id,name,local);

 insert into testind3(id) values(1);
 insert into testind3(id) values(1);

 insert into testind3(id,name) values(1,null);
 insert into testind3(id,name) values(1,'a');
insert into testind3(id,name,local) values(1,null,'SZ');

 insert into testind3(id,name) values(1,'b');
 insert into testind3(id,name,local) values(1,'b','');

-------------------------------------------------------------------
create index ind_a0806 on a0806(object_type,object_id);
select object_id,object_type from a0806 where object_id=1000;

create index ind_a0806 on a0806(object_id,object_type);
create index ind_a0806 on a0806(object_type,object_id);
SQL> select OBJECT_NAME,OBJECT_ID,OBJECT_TYPE from dba_objects where OBJECT_NAME=XXX and OBJECT_id= 
----------------------

SQL> create table b0806U as select * from dba_objects;

Table created.

SQL> 
SQL> select count(*) from b0806U;

  COUNT(*)
----------
     75312


Execution Plan
----------------------------------------------------------
Plan hash value: 1290734131

--------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |   293   (1)| 00:00:04 |
|   1 |  SORT AGGREGATE    |       |     1 |            |          |
|   2 |   TABLE ACCESS FULL| B0806 | 72930 |   293   (1)| 00:00:04 |
--------------------------------------------------------------------

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


Statistics
----------------------------------------------------------
          6  recursive calls
          0  db block gets
       1143  consistent gets
       1345  physical reads
          0  redo size
        424  bytes sent via SQL*Net to client
        420  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

动态分析		  
------------------		  
Analyze table b0806U compute statistics;

SQL> Analyze table b0806U compute statistics;

Table analyzed.

SQL> 
SQL> 
SQL> 
SQL>  select count(*) from b0806U;

  COUNT(*)
----------
     75312


Execution Plan
----------------------------------------------------------
Plan hash value: 1290734131

--------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |   293   (1)| 00:00:04 |
|   1 |  SORT AGGREGATE    |       |     1 |            |          |
|   2 |   TABLE ACCESS FULL| B0806 | 75312 |   293   (1)| 00:00:04 |
--------------------------------------------------------------------


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1075  consistent gets
          0  physical reads
          0  redo size
        424  bytes sent via SQL*Net to client
        420  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> 


SQL> create table c0806 as select * from dba_objects;

Table created.

SQL> select count(*) from c0806 where object_type='VIEW';

  COUNT(*)
----------
      5175


Execution Plan
----------------------------------------------------------
Plan hash value: 1298262899

----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |    11 |   294   (1)| 00:00:04 |
|   1 |  SORT AGGREGATE    |       |     1 |    11 |            |          |
|*  2 |   TABLE ACCESS FULL| C0806 |  5474 | 60214 |   294   (1)| 00:00:04 |
----------------------------------------------------------------------------

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

   2 - filter("OBJECT_TYPE"='VIEW')

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


Statistics
----------------------------------------------------------
          7  recursive calls
          0  db block gets
       1138  consistent gets
       1329  physical reads
          0  redo size
        423  bytes sent via SQL*Net to client
        420  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

		  
收集统计信息
SQL> Analyze table c0806 compute statistics;



SQL> select count(*) from c0806 where object_type='VIEW';

  COUNT(*)
----------
      5175


Execution Plan
----------------------------------------------------------
Plan hash value: 1298262899

----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |     8 |   294   (1)| 00:00:04 |
|   1 |  SORT AGGREGATE    |       |     1 |     8 |            |          |
|*  2 |   TABLE ACCESS FULL| C0806 |  1674 | 13392 |   294   (1)| 00:00:04 |
----------------------------------------------------------------------------

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

   2 - filter("OBJECT_TYPE"='VIEW')


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1075  consistent gets
          0  physical reads
          0  redo size
        423  bytes sent via SQL*Net to client
        420  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed




  1* select count(distinct object_type) from dba_objects
  45
  
  SQL> select count(*) from c0806;

  COUNT(*)
----------
     75313
	 
	 
	 SQL> select 75313/45 from dual;

  75313/45
----------
1673.62222
	 
	 
收集直方图	 
begin
dbms_stats.gather_table_stats(ownname => 'SYS',
                                tabname=>'C0806',
                               estimate_percent => 100,
                               method_opt => 'for all columns size skewonly'
                              );
end;
/
	 
SQL> select count(*) from c0806 where object_type='VIEW';



SQL> select count(*) from c0806 where object_type='VIEW';

  COUNT(*)
----------
      5175


Execution Plan
----------------------------------------------------------
Plan hash value: 1298262899

----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |     9 |   294   (1)| 00:00:04 |
|   1 |  SORT AGGREGATE    |       |     1 |     9 |            |          |
|*  2 |   TABLE ACCESS FULL| C0806 |  5175 | 46575 |   294   (1)| 00:00:04 |
----------------------------------------------------------------------------

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

   2 - filter("OBJECT_TYPE"='VIEW')


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1075  consistent gets
          0  physical reads
          0  redo size
        423  bytes sent via SQL*Net to client
        420  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> 

总结:

1.一个列如果是索引列,null值不存索引树中

2.索引其实也是数据库的对象,占用数据库存储,你可以在脑力里想象出一颗B*Tree结构

3.索引树的叶子节点保存了索引列的值,及索引列对应的行rowid物理地址

 

你可能感兴趣的:(oracle成长记)