1. 程式人生 > >oracle 分頁優化(stopkey)

oracle 分頁優化(stopkey)

SQL優化
stopkey技術是一種預測技術,完全是為了適應大量資料的出現而出現的

從名稱就可以看出,stopkey就是在關鍵位置上停止,終止的技術,oracle這裡指的就是不再繼續讀取剩餘的資料.

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

1.建立測試表

create table vast as select * from dba_objects;
2.準備測試資料 開啟執行計劃 SQL> insert into vast select * from dba_objects; 72554 rows created. 3.測試,提取從500條到1000條資料
SQL> set autotrace on explain 第一種情況 SQL> select * from (select rownum r,a.* from vast a) where r>500 and r<1000; 已用時間: 00: 00: 07.13 執行計劃 ---------------------------------------------------------- Plan hash value: 2564315607
---------------------------------------------------------------------------- | Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     | ---------------------------------------------------------------------------- |   0 | SELECT STATEMENT    |      |   127K|    26M|   562   (1)| 00:00:07 | |*  1 |  VIEW               |      |   127K|    26M|   562   (1)| 00:00:07 | |   2 |   COUNT             |      |       |       |            |          | |   3 |    TABLE ACCESS FULL| VAST |   127K|    25M|   562   (1)| 00:00:07 | ----------------------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
   1 - filter("R"<1000 AND "R">500)
Note -----    - dynamic sampling used for this statement (level=2)

Statistics ----------------------------------------------------------           0  recursive calls           0  db block gets        2102  consistent gets
          0  physical reads           0  redo size       29806  bytes sent via SQL*Net to client         886  bytes received via SQL*Net from client          35  SQL*Net roundtrips to/from client           0  sorts (memory)           0  sorts (disk)         499  rows processed

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

第二種情況


 select * from (select rownum r,a.* from vast a where rownum<1000) where r>500;

已用時間: 00: 00: 07.35

執行計劃
----------------------------------------------------------
---------------------------------------------------------- Plan hash value: 1948416614
---------------------------------------------------------------------------- | Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     | ---------------------------------------------------------------------------- |   0 | SELECT STATEMENT    |      |   999 |   214K|     7  (15)| 00:00:01 | |*  1 |  VIEW               |      |   999 |   214K|     7  (15)| 00:00:01 | |*  2 |   COUNT STOPKEY     |      |       |       |            |          | |   3 |    TABLE ACCESS FULL| VAST |   127K|    25M|     7  (15)| 00:00:01 | ----------------------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
   1 - filter("R">500)    2 - filter(ROWNUM<1000)
Note -----    - dynamic sampling used for this statement (level=2)

Statistics ----------------------------------------------------------           0  recursive calls           0  db block gets         50  consistent gets           0  physical reads           0  redo size       29806  bytes sent via SQL*Net to client         886  bytes received via SQL*Net from client          35  SQL*Net roundtrips to/from client           0  sorts (memory)           0  sorts (disk)         499  rows processed ----------------------------------------------------------

第二種情況比第一種一致性讀大大減小,主要是把rownum引入到了第二層,注意執行計劃中的stopkey,專門是為了提取top n 的需求優化的。

再來句簡單的

select * from vast where rownum < 5;

已用時間: 00: 00: 00.04

執行計劃 ---------------------------------------------------------- Plan hash value: 338940916
--------------------------------------------------------------------------- | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     | --------------------------------------------------------------------------- |   0 | SELECT STATEMENT   |      |     4 |   828 |     3  (34)| 00:00:01 | |*  1 |  COUNT STOPKEY     |      |       |       |            |          | |   2 |   TABLE ACCESS FULL| VAST |   127K|    25M|     3  (34)| 00:00:01 | ---------------------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
   1 - filter(ROWNUM<5)
Note -----    - dynamic sampling used for this statement (level=2)

Statistics ----------------------------------------------------------           8  recursive calls           0  db block gets         129  consistent gets           0  physical reads           0  redo size        1896  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)           4  rows processed 條件中有rownum存在,就會有stopkey優化 ,那越往後分頁是否速度就會一致性讀就會越大呢? select * from (select rownum r,a.* from vast a where rownum <= 70000) where r > 69000; 已用時間: 00: 00: 04.24 執行計劃 ---------------------------------------------------------- Plan hash value: 1948416614
---------------------------------------------------------------------------- | Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     | ---------------------------------------------------------------------------- |   0 | SELECT STATEMENT    |      | 70000 |    14M|   310   (1)| 00:00:04 | |*  1 |  VIEW               |      | 70000 |    14M|   310   (1)| 00:00:04 | |*  2 |   COUNT STOPKEY     |      |       |       |            |          | |   3 |    TABLE ACCESS FULL| VAST |   127K|    25M|   310   (1)| 00:00:04 | ----------------------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
   1 - filter("R">69000)    2 - filter(ROWNUM<=70000)
Note -----    - dynamic sampling used for this statement (level=2)

Statistics ----------------------------------------------------------           7  recursive calls           0  db block gets        1189  consistent gets           0  physical reads           0  redo size       64623  bytes sent via SQL*Net to client        1249  bytes received via SQL*Net from client          68  SQL*Net roundtrips to/from client           0  sorts (memory)           0  sorts (disk)        1000  rows processed 看來 stopkey 還是要注意 不能在rownum過大的時候使用。