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)


結論:創建索引的時候,要選擇那些鍵值重複率低的字段。否則是很難用上的。







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