oracle 分頁優化(stopkey)
阿新 • • 發佈:2018-12-16
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條資料
---------------------------------------------------------------------------- | 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
-----------------------------------------------------------------------------------------------------------------------------------
第二種情況
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過大的時候使用。