7.索引的性能分析

2013-08-07 星期三 天气:晴

-------------------------------索引的性能分析-----------------------


场景:假设数据块的大小8000字节,查询返回的记录行数是整表记录的20%


1、表有100000行数据,返回20000行数据,假如每行80字节,1块=100行,全表有1000块,

  查询到的对应的叶子行有20000个,扫索引扫20000块次,全表扫,扫1000块次。

2、表有100000行数据,返回20000行数据,假如每行800字节,1块=10行,全表有10000块,

  查询到的对应的叶子行有20000个,扫索引扫20000块次,全表扫,扫10000块次。

3、表有100000行数据,返回20000行数据,假如每行1600字节,1块=5行,全表有20000块,

  查询到的对应的叶子行有20000个,扫索引扫20000块次,全表扫,扫20000块次。

4、表有100000行数据,返回20000行数据,假如每行8000字节,1块=1行,全表有100000块,

  查询到的对应的叶子行有20000个,扫索引扫20000块次,全表扫,扫100000块次。


归纳:

 A 不一定使用索引查询效率就会提升,场景1个场景2反而会下降。

 B 索引的使用和块、行的比例有关系,块中含有的行越多扫索引的效率就会越低,

   块中含有的行越少,扫索引的效率就会越高。和行的密度的有关系。


案例:研究RBO优化法则和CBO性能分析的差别


1、创建一个案例表

SQL> create table tx as select 1 id,object_name from all_objects;


Table created.


SQL> update tx set id=99 where rownum=1;


1 row updated.


SQL> commit;


Commit complete.




2、用RBO优化器生成执行计划


SQL> set autotrace trace exp

SQL> select /*+ rule */ * from tx where id=1;


Execution Plan

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

Plan hash value: 40191160


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

| Id  | Operation         | Name |

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

|   0 | SELECT STATEMENT  |      |

|*  1 |  TABLE ACCESS FULL| TX   |  --全表扫描

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


Predicate Information (identified by operation id):

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


  1 - filter("ID"=1)


Note

-----

  - rule based optimizer used (consider using cbo)


SQL> create index ind_tx on tx(id);


Index created.


SQL> exec dbms_stats.gather_table_stats(user,'tx',cascade=>true);


PL/SQL procedure successfully completed.


SQL> select /*+ rule */ * from tx where id=1;


Execution Plan

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

Plan hash value: 2614573569


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

| Id  | Operation                   | Name   |

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

|   0 | SELECT STATEMENT            |        |

|   1 |  TABLE ACCESS BY INDEX ROWID| TX     |

|*  2 |   INDEX RANGE SCAN          | IND_TX |  --RBO下只要有索引一定会强制走索引的。

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


Predicate Information (identified by operation id):

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


  2 - access("ID"=1)


Note

-----

  - rule based optimizer used (consider using cbo)



SQL> select /*+ rule */ * from tx where id=99;


Execution Plan

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

Plan hash value: 2614573569


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

| Id  | Operation                   | Name   |

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

|   0 | SELECT STATEMENT            |        |

|   1 |  TABLE ACCESS BY INDEX ROWID| TX     |

|*  2 |   INDEX RANGE SCAN          | IND_TX |

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


Predicate Information (identified by operation id):

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


  2 - access("ID"=99)


Note

-----

  - rule based optimizer used (consider using cbo)


================================================


3、用CBO生成执行计划


SQL> select  * from tx where id=1;


Execution Plan

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

Plan hash value: 40191160


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

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

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

|   0 | SELECT STATEMENT  |      | 40919 |  1118K|    47   (3)| 00:00:01 |

|*  1 |  TABLE ACCESS FULL| TX   | 40919 |  1118K|    47   (3)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  1 - filter("ID"=1)


SQL> select /*+ index(tx ind_tx) */ * from tx where id=1;  --CBO下,强制走索引代价很大。


Execution Plan

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

Plan hash value: 2614573569


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

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

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

|   0 | SELECT STATEMENT            |        | 40919 |  1118K|   273   (1)| 00:00:04 |

|   1 |  TABLE ACCESS BY INDEX ROWID| TX     | 40919 |  1118K|   273   (1)| 00:00:04 |

|*  2 |   INDEX RANGE SCAN          | IND_TX | 40919 |       |    81   (2)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("ID"=1)




SQL> set linesize 1000

SQL> select  * from tx where id=99;


Execution Plan

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

Plan hash value: 2614573569


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

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

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

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

|   1 |  TABLE ACCESS BY INDEX ROWID| TX     |     1 |    28 |     2   (0)| 00:00:01 |

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

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


Predicate Information (identified by operation id):

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


  2 - access("ID"=99)



查询列值分布数量很高的值,会全表扫,反之,才可能会用索引。



影响索引使用效率的三个影响因素:

1、块中行的密度

2、查询语句中where条件中的索引列引用值在列值中的分布情况。

3、索引和表数据放在同一个磁盘上,会发生IO的争用。




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

案例:分析B树索引的性能


SQL> drop table t1;

drop table t1

          *

ERROR at line 1:

ORA-00942: table or view does not exist



SQL> create table t1(id int primary key,name varchar2(10));


Table created.


SQL> begin

 2  for i in 1..10000 loop

 3  insert into t1 values(i,'T1');

 4  end loop;

 5  commit;

 6  end;

 7  /


PL/SQL procedure successfully completed.


SQL> create table t2(id int primary key,name varchar2(10));


Table created.


SQL> begin

 2  for i in 1..1000000 loop

 3  insert into t2 values(i,'T2');

 4  end loop;

 5  commit;

 6  end;

 7  /


PL/SQL procedure successfully completed.



SQL> exec dbms_stats.gather_table_stats(user,'t1',cascade=>true);


PL/SQL procedure successfully completed.


SQL> exec dbms_stats.gather_table_stats(user,'t2',cascade=>true);


PL/SQL procedure successfully completed.


SQL> set autotrace trace exp    --显示执行计划

SQL> select * from t1 where id=100;


Execution Plan

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

Plan hash value: 1846342996


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

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

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

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

|   1 |  TABLE ACCESS BY INDEX ROWID| T1          |     1 |     6 |     2   (0)| 00:00:01 |

|*  2 |   INDEX UNIQUE SCAN         | SYS_C006531 |     1 |       |     1   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("ID"=100)


SQL> select * from t2 where id=100;


Execution Plan

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

Plan hash value: 3288443420


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

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

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

|   0 | SELECT STATEMENT            |             |     1 |     7 |     3   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| T2          |     1 |     7 |     3   (0)| 00:00:01 |

|*  2 |   INDEX UNIQUE SCAN         | SYS_C006532 |     1 |       |     2   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("ID"=100)



T1表的索引数只有两层,但是T2表的平衡树有三层,T3表在读取索引的时候会多读取一个根块。




查询层数:

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

select * from user_indexes;      --首先查看对应表的索引名


analyze index 索引名 validate structure; --分析


select * from index_stats    --查看索引的统计信息


如下:

SQL> analyze index ind_obj_id validate structure;

Index analyzed


SQL> select * from index_stats;

   HEIGHT     BLOCKS NAME                           PARTITION_NAME                    LF_ROWS    LF_BLKS LF_ROWS_LEN LF_BLK_LEN    BR_ROWS    BR_BLKS BR_ROWS_LEN BR_BLK_LEN DEL_LF_ROWS DEL_LF_ROWS_LEN DISTINCT_KEYS MOST_REPEATED_KEY BTREE_SPACE USED_SPACE   PCT_USED ROWS_PER_KEY BLKS_GETS_PER_ACCESS   PRE_ROWS PRE_ROWS_LEN OPT_CMPR_COUNT OPT_CMPR_PCTSAVE

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

        2        384 IND_OBJ_ID                                                        115766        273     1843607       7996        272          1        3750       8028       52956          839277         38598                 3     2190936    1847357         85 2.9992745738     3.99963728690606          0            0              1                8


两次查询的代价是一样的,有了B树索引之后,查询的损耗不会因为表数据量的增加而增加,

即使数据量相差很大,当在唯一性索引或者主键索引查询的时候,消耗的资源几乎是没有区别的,

这就是索引发挥的巨大作用。


如果没有索引:


SQL> select /*+ full(t1) */ * from t1 where id=100;


Execution Plan

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

Plan hash value: 3617692013


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

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

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

|   0 | SELECT STATEMENT  |      |     1 |     6 |     6   (0)| 00:00:01 |

|*  1 |  TABLE ACCESS FULL| T1   |     1 |     6 |     6   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  1 - filter("ID"=100)


SQL> select /*+ full(t2) */ * from t2 where id=100;


Execution Plan

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

Plan hash value: 1513984157


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

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

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

|   0 | SELECT STATEMENT  |      |     1 |     7 |   444   (7)| 00:00:06 |

|*  1 |  TABLE ACCESS FULL| T2   |     1 |     7 |   444   (7)| 00:00:06 |

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


Predicate Information (identified by operation id):

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


  1 - filter("ID"=100)




update操作中索引的影响


SQL> update t1 set id=10001 where id=100;


1 row updated.



Execution Plan

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

Plan hash value: 2799287261


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

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

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

|   0 | UPDATE STATEMENT   |             |     1 |     4 |     1   (0)| 00:00:01 |

|   1 |  UPDATE            | T1          |       |       |            |          |

|*  2 |   INDEX UNIQUE SCAN| SYS_C006531 |     1 |     4 |     1   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("ID"=100)


SQL> update /*+ full(t1) */ t1 set id=10001 where id=100;


0 rows updated.



Execution Plan

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

Plan hash value: 2927627013


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

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

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

|   0 | UPDATE STATEMENT   |      |     1 |     4 |     6   (0)| 00:00:01 |

|   1 |  UPDATE            | T1   |       |       |            |          |

|*  2 |   TABLE ACCESS FULL| T1   |     1 |     4 |     6   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - filter("ID"=100)


SQL> rollback;


Rollback complete.


SQL> update t2 set id=1000001 where id=100;


1 row updated.



Execution Plan

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

Plan hash value: 3398718552


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

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

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

|   0 | UPDATE STATEMENT   |             |     1 |     5 |     2   (0)| 00:00:01 |

|   1 |  UPDATE            | T2          |       |       |            |          |

|*  2 |   INDEX UNIQUE SCAN| SYS_C006532 |     1 |     5 |     2   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("ID"=100)


SQL> update /*+ full(t2) */ t2 set id=1000001 where id=100;


0 rows updated.



Execution Plan

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

Plan hash value: 2722410703


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

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

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

|   0 | UPDATE STATEMENT   |      |     1 |     5 |   444   (7)| 00:00:06 |

|   1 |  UPDATE            | T2   |       |       |            |          |

|*  2 |   TABLE ACCESS FULL| T2   |     1 |     5 |   444   (7)| 00:00:06 |

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


Predicate Information (identified by operation id):

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


  2 - filter("ID"=100)


SQL> rollback;


Rollback complete.




delete操作:

SQL> delete from t2 where id=100;


1 row deleted.



Execution Plan

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

Plan hash value: 1328729220


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

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

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

|   0 | DELETE STATEMENT   |             |     1 |     5 |     2   (0)| 00:00:01 |

|   1 |  DELETE            | T2          |       |       |            |          |

|*  2 |   INDEX UNIQUE SCAN| SYS_C006532 |     1 |     5 |     2   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("ID"=100)


SQL> delete /*+ full(t2) */ from t2 where id=100;


0 rows deleted.



Execution Plan

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

Plan hash value: 1451993194


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

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

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

|   0 | DELETE STATEMENT   |      |     1 |     5 |   444   (7)| 00:00:06 |

|   1 |  DELETE            | T2   |       |       |            |          |

|*  2 |   TABLE ACCESS FULL| T2   |     1 |     5 |   444   (7)| 00:00:06 |

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


Predicate Information (identified by operation id):

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


  2 - filter("ID"=100)


SQL> rollback;


Rollback complete.




注意:一定要where中用到索引列才能走索引:


SQL> update t2 set name='T11' where name='T2';  --没有用到索引列是一定不会走索引的。


1000000 rows updated.



Execution Plan

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

Plan hash value: 2722410703


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

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

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

|   0 | UPDATE STATEMENT   |      |  1013K|  2970K|   447   (8)| 00:00:06 |

|   1 |  UPDATE            | T2   |       |       |            |          |

|*  2 |   TABLE ACCESS FULL| T2   |  1013K|  2970K|   447   (8)| 00:00:06 |

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


Predicate Information (identified by operation id):

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


  2 - filter("NAME"='T2')


SQL> update /*+ index(t2 SYS_C006532) */ t2 set name='T11' where name='T2';  --强制走索引代价巨大


1000000 rows updated.



Execution Plan

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

Plan hash value: 1100077776


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

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

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

|   0 | UPDATE STATEMENT             |             |  1013K|  2970K|  3728   (2)| 00:00:45 |

|   1 |  UPDATE                      | T2          |       |       |            |          |

|*  2 |   TABLE ACCESS BY INDEX ROWID| T2          |  1013K|  2970K|  3728   (2)| 00:00:45 |

|   3 |    INDEX FULL SCAN           | SYS_C006532 |  1013K|       |  1907   (2)| 00:00:23 |

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


Predicate Information (identified by operation id):

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


  2 - filter("NAME"='T2')


插入数据的PLAN


SQL> insert into t1 values(10001,'T11');


1 row created.



Execution Plan

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


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

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

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

|   0 | INSERT STATEMENT |      |     1 |     6 |     1   (0)| 00:00:01 |

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


A 在HWM以下找连续的空间将数据插入

B 没有找到,在HWM之上插入数据,后HWM上移。



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


块中的行的分布密度对使用索引的影响。


SQL> conn hr/hr

Connected.

SQL> create table t3(id int primary key,name1 varchar2(2000),name2 varchar2(2000));  --行密度大的表


Table created.


SQL> create table t4(id int primary key,name1 char(2000),name2 char(2000));  --行密度小的表


Table created.


块大小是8K,预留10%的空间,实际每个块能存7373个字节,T4表的块只能放一行数据。


SQL> begin

 2  for i in 1..20000 loop

 3  insert into t3 values(i,'T3','T31');

 4  end loop;

 5  commit;

 6  end;

 7  /


PL/SQL procedure successfully completed.


SQL> begin

 2  for i in 1..20000 loop

 3  insert into t4 values(i,'T4','T41');

 4  end loop;

 5  commit;

 6  end;

 7  /


PL/SQL procedure successfully completed.


SQL> exec dbms_stats.gather_table_stats(user,'t3',estimate_percent=>100,cascade=>true);


PL/SQL procedure successfully completed.


SQL> exec dbms_stats.gather_table_stats(user,'t4',estimate_percent=>100,cascade=>true);


PL/SQL procedure successfully completed.


SQL> select * from t3 where id>17000;


Execution Plan

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

Plan hash value: 4161002650


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

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

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

|   0 | SELECT STATEMENT  |      |  3000 | 33000 |    14   (8)| 00:00:01 |

|*  1 |  TABLE ACCESS FULL| T3   |  3000 | 33000 |    14   (8)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  1 - filter("ID">17000)


SQL> select * from t4 where id>17000;  --行密度小的越容易用索引


Execution Plan

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

Plan hash value: 1161789439


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

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

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

|   0 | SELECT STATEMENT            |             |  3000 |    11M|  3011   (1)| 00:00:37 |

|   1 |  TABLE ACCESS BY INDEX ROWID| T4          |  3000 |    11M|  3011   (1)| 00:00:37 |

|*  2 |   INDEX RANGE SCAN          | SYS_C006534 |  3000 |       |     7   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("ID">17000)


SQL> set autotrace trace exp stat

SQL> select /*+ index(t3 SYS_C006533) */ * from t3 where id>17000;


3000 rows selected.



Execution Plan

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

Plan hash value: 2289016736


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

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

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

|   0 | SELECT STATEMENT            |             |  3000 | 33000 |    14   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| T3          |  3000 | 33000 |    14   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | SYS_C006533 |  3000 |       |     7   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("ID">17000)



Statistics

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

         0  recursive calls

         0  db block gets

       415  consistent gets   --走索引一致性读还是有差别的

         0  physical reads

         0  redo size

     55787  bytes sent via SQL*Net to client

      2589  bytes received via SQL*Net from client

       201  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

      3000  rows processed


SQL> select * from t3 where id>17000;


3000 rows selected.



Execution Plan

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

Plan hash value: 4161002650


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

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

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

|   0 | SELECT STATEMENT  |      |  3000 | 33000 |    14   (8)| 00:00:01 |

|*  1 |  TABLE ACCESS FULL| T3   |  3000 | 33000 |    14   (8)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  1 - filter("ID">17000)



Statistics

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

         0  recursive calls

         0  db block gets

       253  consistent gets

         0  physical reads

         0  redo size

     55787  bytes sent via SQL*Net to client

      2589  bytes received via SQL*Net from client

       201  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

      3000  rows processed



T3表块上行分布密度比较大,用索引的概率小。T4表块上行分布密度小,用索引的概率大。


注意:上面这个实验要找到临界值才能成功的,临界值就是返回就录行数的值,

     在这个值上走索引和全表扫的性能是一样的。



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


案例:B树索引使用的场合——键值重复率低的字段适合创建B树索引


SQL> create table t5 as select object_id,object_name from all_objects;


Table created.


SQL> create table t6 as select mod(object_id,2) object_id,object_name from all_objects;  --ID字段重复率很高


Table created.


SQL> create index t3_ind on t5(object_id);


Index created.


SQL> create index t6_ind on t6(object_id);


Index created.


SQL> select count(distinct object_id) from t5;


COUNT(DISTINCTOBJECT_ID)

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

                  40929


SQL> select count(distinct object_id) from t6;


COUNT(DISTINCTOBJECT_ID)

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

                      2


SQL> exec dbms_stats.gather_table_stats(user,'t5',estimate_percent=>100,cascade=>true);


PL/SQL procedure successfully completed.


SQL> exec dbms_stats.gather_table_stats(user,'t6',estimate_percent=>100,cascade=>true);


PL/SQL procedure successfully completed.


SQL> select * from t5 where object_id=1;


no rows selected



Execution Plan

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

Plan hash value: 3812361271


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

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

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

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

|   1 |  TABLE ACCESS BY INDEX ROWID| T5     |     1 |    30 |     2   (0)| 00:00:01 |

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

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


Predicate Information (identified by operation id):

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


  2 - access("OBJECT_ID"=1)



Statistics

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

         1  recursive calls

         0  db block gets

         2  consistent gets

         0  physical reads

         0  redo size

       339  bytes sent via SQL*Net to client

       389  bytes received via SQL*Net from client

         1  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

         0  rows processed


SQL> select * from t6 where object_id=1;


20511 rows selected.



Execution Plan

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

Plan hash value: 1930642322


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

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

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

|   0 | SELECT STATEMENT  |      | 20465 |   539K|    46   (3)| 00:00:01 |

|*  1 |  TABLE ACCESS FULL| T6   | 20465 |   539K|    46   (3)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  1 - filter("OBJECT_ID"=1)



Statistics

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

         1  recursive calls

         0  db block gets

      1556  consistent gets

         0  physical reads

         0  redo size

    626252  bytes sent via SQL*Net to client

     15437  bytes received via SQL*Net from client

      1369  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

     20511  rows processed


强制T6走索引的话

SQL> select /*+ index(t6 T6_IND) */ * from t6 where object_id=1;


20511 rows selected.



Execution Plan

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

Plan hash value: 1497073299


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

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

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

|   0 | SELECT STATEMENT            |        | 20465 |   539K|   228   (1)| 00:00:03 |

|   1 |  TABLE ACCESS BY INDEX ROWID| T6     | 20465 |   539K|   228   (1)| 00:00:03 |

|*  2 |   INDEX RANGE SCAN          | T6_IND | 20465 |       |    40   (3)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  2 - access("OBJECT_ID"=1)



Statistics

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

         1  recursive calls

         0  db block gets

      2954  consistent gets

         0  physical reads

         0  redo size

    626252  bytes sent via SQL*Net to client

     15437  bytes received via SQL*Net from client

      1369  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

     20511  rows processed


oracle先要扫索引的叶子行,找到符合条件的键值,根据键值中的rowid到表中找到对应的行。

如果满足的条件很多,oracle不停的访问索引再访问表,如此循环。


SQL> select object_id from t5 where object_id=1;  --查询索引列,不需要用rowid再去访问表了,

                                                  因为查询索引已经满足了要求。


no rows selected



Execution Plan

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

Plan hash value: 2377336880


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

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

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

|   0 | SELECT STATEMENT |        |     1 |     5 |     1   (0)| 00:00:01 |

|*  1 |  INDEX RANGE SCAN| T3_IND |     1 |     5 |     1   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  1 - access("OBJECT_ID"=1)


SQL> select object_id from t6 where object_id=1;


20511 rows selected.



Execution Plan

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

Plan hash value: 3707116216


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

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

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

|   0 | SELECT STATEMENT     |        | 20465 | 61395 |    20   (5)| 00:00:01 |

|*  1 |  INDEX FAST FULL SCAN| T6_IND | 20465 | 61395 |    20   (5)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


  1 - filter("OBJECT_ID"=1)


结论:创建索引的时候,要选择那些键值重复率低的字段。否则是很难用上的。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章