oracle高效分頁查詢總結

本文參考連接:http://blog.sina.com.cn/s/blog_8604ca230100vro9.htmlhtml

探索查詢語句:mysql

--分頁參數:size = 20 page = 2
--沒有order by的查詢
-- 嵌套子查詢,兩次篩選(推薦使用)
--SELECT *
-- FROM (SELECT ROWNUM AS rowno, t.*
-- FROM DONORINFO t
-- WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd')
-- AND TO_DATE ('20060731', 'yyyymmdd')
-- AND ROWNUM <= 20*2) table_alias
-- WHERE table_alias.rowno > 20*(2-1);        --耗時0.05s

-- 一次篩選(數據量大的時候,第一次查詢的數據量過大,明顯比上面慢,不推薦)
--select * from(
--SELECT ROWNUM AS rowno, t.*
--FROM DONORINFO t
--WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') AND TO_DATE ('20060731', 'yyyymmdd')
--) r
--where r.rowno BETWEEN 20*(2-1)+1 and 20*2;      --耗時0.46s


--有order by的查詢
--嵌套子查詢,兩次篩選(推薦使用)
--SELECT *
--FROM (SELECT ROWNUM AS rowno,r.*
-- FROM(
-- SELECT * FROM DONORINFO t
-- WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd')
-- AND TO_DATE ('20060731', 'yyyymmdd')
-- ORDER BY t.BIRTHDAY desc
-- ) r
-- where ROWNUM <= 20*2 
-- ) table_alias
-- WHERE table_alias.rowno > 20*(2-1);                --耗時0.744s

-- 一次篩選(數據量大的時候,第一次查詢的數據量過大,明顯比上面慢,不推薦)
--select * from (
--SELECT ROWNUM AS rowno,r.*
--FROM(
--SELECT * FROM DONORINFO t
--WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd')
--AND TO_DATE ('20060731', 'yyyymmdd')
--ORDER BY t.BIRTHDAY desc
--) r
----where ROWNUM <= 20; --這裏用>查不到數據 =也查不到數據 <= 或者 < 能夠查到數據 
----where ROWNUM BETWEEN 20*(2-1)+1 AND 20*2; --查不到數據
----where ROWNUM <=20*2 and ROWNUM > 20*(2-1); --查不到數據
----這是由於查詢時,第一條生成的rownum爲1,1>20不成立,1=20也不成立,因此這條數據就做廢了,依次類推,這樣就查不到任何一條數據
--) t 
--where t.rowno <=20*2 and t.rowno > 20*(2-1); --能夠查到數據耗時:3.924s
---- where t.rowno BETWEEN 20*(2-1)+1 AND 20*2; --能夠查到數據耗時:3.919s

--採用row_number() over 分頁函數
--select * 
--from(select d.*,row_number() over(order by d.BIRTHDAY) as rownumber 
--     from DONORINFO d
--     WHERE d.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd')
--                             AND TO_DATE ('20060731', 'yyyymmdd')
-- ) p 
--where p.rownumber BETWEEN 20*(2-1)+1 AND 20*2;  --耗時0.812s

select * from (
select * 
from(select d.*,row_number() over(order by d.BIRTHDAY) as rownumber 
     from DONORINFO d
     WHERE d.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd')
                             AND TO_DATE ('20060731', 'yyyymmdd')
 ) p 
where p.rownumber <20*2
) where rownumber > 20*(2-1);    -- 耗時0.813s

 

從以上探索比較,咱們得知:sql

一、ROWNUM數據庫

  rownum老是從1開始的,第一條不知足去掉的話,第二條的rownum 又成了1。依此類推,因此永遠沒有不知足條件的記錄。函數

    能夠這樣理解:rownum是一個序列,是Oracle數據庫從數據文件或緩衝區中讀取數據的順序。spa

    它取得第一條記錄則rownum值爲1,第二條爲2。依次類推。.net

    當使用「>、>=、=、between...and」這些條件時,從緩衝區或數據文件中獲得的第一條記錄的rownum爲1,不符合sql語句的條件,會被刪除,接着取下條。code

    下條的rownum還會是1,又被刪除,依次類推,便沒有了數據。htm

  因此上限條件必須放在子查詢,而下限條件必須放在外層查詢。blog

二、between  and 和 >= and <=

這二者查詢效率上來講沒有區別,between and 最終也是轉爲>= and <=

因此select * from (select * from a where a.time >= to_date('19920324','yyyymmdd')) b where b.time <= to_date('20170324','yyyymmdd')

這樣的嵌套是沒有必要的,能夠直接用between and。

三、Oracle通用分頁格式

對於沒有order by語句的分頁:

SELECT *
FROM (SELECT ROWNUM AS rowno, t.*
          FROM DONORINFO t
          WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') AND TO_DATE ('20060731', 'yyyymmdd') AND ROWNUM <= page*size) table_alias WHERE table_alias.rowno > (page-1)*size; 

有order by語句的分頁

SELECT *
FROM (SELECT ROWNUM AS rowno,r.*
           FROM(SELECT * FROM DONORINFO t
                    WHERE t.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd') AND TO_DATE ('20060731', 'yyyymmdd') ORDER BY t.BIRTHDAY desc ) r where ROWNUM <= page*size ) table_alias WHERE table_alias.rowno > (page-1)*size;

另外咱們也可使用row_number() over函數:

select * 
from(select d.*,row_number() over(order by d.BIRTHDAY) as rownumber 
       from DONORINFO d
       WHERE d.BIRTHDAY BETWEEN TO_DATE ('19800101', 'yyyymmdd')
        AND TO_DATE ('20060731', 'yyyymmdd')
 ) p 
where p.rownumber BETWEEN size*(page-1)+1 AND page*size;

可是相比前面的並無什麼優點。

相關文章
相關標籤/搜索