oracle 分页_80分页查询,不止写法
????據孔老先生說,茴香豆的茴字有四種寫法,那oracle的分頁查詢又有多少種寫法呢?
分頁查詢,其實本質上就是topN查詢的變種, 如果把topN的一部分結果集去掉,就變成了分頁.
topN的基本寫法,兩層select,第一層先order by,第二層再用rownum:
select owner,object_name,object_id,rownum as rn from(select?* from t1?where owner='SYS'?order by object_id desc)?where rownum<=20;
有些初級開發(fā)人員有時會寫成:
select owner,object_name,object_id,rownum as rn from?t1?where owner='SYS'? and?rownum<=20 order by object_id desc;
這種寫法的邏輯可能存在問題,因為sql解析時會先執(zhí)行rownum,隨機先選出20條記錄,再執(zhí)行排序.?而不是常見業(yè)務需要的先排序,再取前20. 如果滿足條件的全部結果集<=20, 那么邏輯也是沒問題的.
在上面topn的基礎上, 再套一層select, 就變成了最常見的標準的三層select的分頁查詢寫法(第一層排序,第二層給rownum取別名,得到topn,第三層去掉topn的前面部分):
select?owner,object_name,object_id,rn from
? (select a.*,rownum as rn from
? ?(select?* from t1?where owner='SYS'?order by object_id desc) a?where rownum<=20
? )?where rn>10;
執(zhí)行計劃中看到COUNT STOPKEY?為最佳(沒有sort字樣).
除了上面比較常見的寫法,?還有其他幾個不常見的寫法:
1層select(12c+才支持的offset 寫法,有時可能需要使用hint來糾正優(yōu)化器執(zhí)行計劃):
select? owner,object_name,object_id,rownum as rn
from t1
where owner='SYS'
order by object_id desc
offset 10 rows fetch next 10 rows only;
執(zhí)行計劃中看到WINDOW NOSORT STOPKEY為最佳
2層select,用到了row_number分析函數(可能需要使用hint來糾正優(yōu)化器執(zhí)行計劃):
SELECT * FROM
? (SELECT? ?owner,object_name,object_id,
? ? ? ? ? ? row_number() over (order by object_id desc) as rn
? ? ? ? ? FROM t1
? ? ? ? where owner='SYS'
)? WHERE RN<= 20 and RN > 10;
執(zhí)行計劃中看到WINDOW NOSORT STOPKEY為最佳
4層select,對于頁數比較大的分頁查詢,某些情況下可以使用:
with tmp as
(SELECT * FROM
? ? ( SELECT rid, ROWNUM as RN
? ? ? ?FROM
? ? ? ? ? ?(SELECT rowid as rid
? ? ? ? ? ? ?FROM t1
? ? ? ? ? ? ?where owner='SYS'
? ? ? ? ? ? ?order by object_id desc
? ? ? ? ? ? ) WHERE ROWNUM <= 500
? ? ) WHERE RN > 490
) select? /*+ use_nl(a) leading(b) */ owner,object_name,object_id,rn
from t1 a,tmp b
where a.rowid=b.rid;
下面的3層寫法,是比較常見的低效分頁寫法,在分頁前結果集大的情況,性能會比較差, 需要避免使用:
select * from
(
select a.*,rownum as rn??
from
(select owner,object_name,object_id
? from t1
? where owner= 'SYS'
? ?order by object_id desc
)a
) where rn>10 and rn<=20;
執(zhí)行計劃一般包含??SORT ORDER BY 的步驟.
掌握了分頁寫法,只是優(yōu)化的第一步,下面我們看一個生產案例,SQL代碼如下:
這是一個取topn的SQL,先取topn(分頁前結果集20萬左右),再left join,寫法完全沒問題,但是執(zhí)行時間還是比較長,需要24秒:
用hint調下執(zhí)行計劃,執(zhí)行時間變成1秒:
hint:??/*+ monitor leading(p o) push_pred(co@sel$2) */
如果再創(chuàng)建一個core_userprofile表上orgid+UpdateDate+id 3字段聯合索引, 那么這個SQL的執(zhí)行時間估計也就是10毫秒以下了. (從24秒到10毫秒,這種性能的提高,靠硬件是無法實現的,現實中確實有很多類似的SQL,可惜的是,我們很多的決策人員, 只相信高級硬件才能解決性能問題,不知道有這些高級優(yōu)化技巧)
總結:
????分頁查詢,寫法只是第一步,寫法正確的基礎上,如果執(zhí)行計劃不佳,我們可以通過oracle優(yōu)化器提供的hint來調整執(zhí)行計劃(不需要改sql代碼); 但是如果sql寫法不佳,也是沒有辦法通過調整索引和執(zhí)行計劃進行優(yōu)化.?
????寫法和索引,是SQL優(yōu)化的核心,在此基礎上通過hint調整執(zhí)行計劃, 是更高級的技術, 需要更進一步的了解優(yōu)化器特性,以人腦優(yōu)化器代替電腦優(yōu)化器.
????想提高SQL優(yōu)化技能,看完我的線上培訓課程(索引專題,SQL寫法與改寫專題)會大有幫助.
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的oracle 分页_80分页查询,不止写法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 初步认识java中的方法
- 下一篇: javascript中parseFloa