不同数据库分页查询的实现
分頁查詢是數據庫查詢中經常用到的一項操作,對查詢出來的結果進行分頁查詢可以方便瀏覽。那么Oracle、SQL Server、MySQL是如何實現查詢的呢?本文我們就來介紹這一部分內容。
1.?SQL Server 分頁查詢
實例:一張表 tbl_FlightsDetail,有300多W記錄,主鍵 FlightsDetailID(Guid),要求按照FlightsDetailID排序 取 3000001 到3000010 之間的10條記錄,也是百萬級。方法1 定位法 (利用ID大于多少)
select top 10 * from tbl_FlightsDetail where FlightsDetailID>(select max(FlightsDetailID) from ( select top 3000000 FlightsDetailID from tbl_FlightsDetail order by FlightsDetailID) as t ) order by FlightsDetailID
先查出 top 300000,再聚合取這個集合中最大的Id1,再過濾 id大于id1的集合(上圖中使用到索引),再取top 10 條。
方法2 (利用Not In)
select top 10* from tbl_FlightsDetail where FlightsDetailID not in (select top 3000000 FlightsDetailID from tbl_FlightsDetail order by FlightsDetailID ) order by FlightsDetailID和方法一類似,只是過濾where條件不一樣,這里用到的是not in,上圖中沒有用到索引,耗時8秒。如果 FlightsDetailID不是索引的話,方法1和該方法將差不多。
其他的查詢方法以及介紹參照:Sql Server 數據分頁
2.?Oracle數據庫分頁查詢
從數據庫表中第M條記錄開始檢索N條記錄SELECT * FROM (SELECT ROWNUM r,t1.* From 表名稱 t1 where rownum < M + N) t2 where t2.r >= M 例如從表Sys_option(主鍵為sys_id)中從10條記錄還是檢索20條記錄,語句如下:
SELECT * FROM (SELECT ROWNUM R,t1.* From Sys_option where rownum < 30 ) t2 Where t2.R >= 10 參考文檔:mysql、sql server、oracle數據庫分頁查詢及分析(操作手冊)
ORACLE分頁查詢SQL語法——最高效的分頁 oracle分頁查詢的效率分析
3. MySQL分頁查詢
方法1: 直接使用數據庫提供的SQL語句語句樣式: SELECT * FROM 表名稱 LIMIT M,N;(從M位置處取N條數據)
適應場景: 適用于數據量較少的情況(元組百/千級)
原因/缺點: 全表掃描,速度會很慢 且 有的數據庫結果集返回不穩定(如某次返回1,2,3,另外的一次返回2,1,3). Limit限制的是從結果集的M位置處取出N條輸出,其余拋棄.
方法2: 建立主鍵或唯一索引, 利用索引(假設每頁10條)
語句樣式:??SELECT * FROM 表名稱 WHERE id_pk > (pageNum*10) LIMIT M;(從pageNum*10處取M條數據)
適應場景: 適用于數據量多的情況(元組數上萬)
原因: 索引掃描,速度會很快. 有朋友提出: 因為數據查詢出來并不是按照pk_id排序的,所以會有漏掉數據的情況,只能方法3
方法3: 基于索引再排序
語句樣式: SELECT * FROM 表名稱 WHERE id_pk > (pageNum*10) ORDER BY id_pk ASC LIMIT M;
適應場景: 適用于數據量多的情況(元組數上萬). 最好ORDER BY后的列對象是主鍵或唯一所以,使得ORDER BY操作能利用索引被消除但結果集是穩定的(穩定的含義,參見方法1)
原因: 索引掃描,速度會很快. 但MySQL的排序操作,只有ASC沒有DESC(DESC是假的,未來會做真正的DESC,期待...).
方法4: (第一個問號表示pageNum,第二個?表示每頁元組數)
語句樣式:? PREPARE stmt_name FROM SELECT * FROM 表名稱 WHERE id_pk > (?* ?) ORDER BY id_pk ASC LIMIT M
適應場景:?大數據量
原因: 索引掃描,速度會很快. prepare語句又比一般的查詢語句快一點。
方法5: 利用MySQL支持ORDER操作可以利用索引快速定位部分元組,避免全表掃描
比如: 讀第1000到1019行元組(pk是主鍵/唯一鍵).
SELECT * FROM your_table WHERE pk>=1000 ORDER BY?pk ASC LIMIT 0,20;
方法6: 利用"子查詢/連接+索引"快速定位元組的位置,然后再讀取元組. 道理同方法5
如(id是主鍵/唯一鍵,藍色字體時變量):
利用子查詢示例:
SELECT * FROM your_table WHERE id <=?
(SELECT id FROM your_table ORDER BY id desc LIMIT?($page-1)*$pagesize?ORDER BY id desc LIMIT?$pagesize
利用連接示例:
SELECT * FROM your_table AS t1?
JOIN (SELECT id FROM your_table ORDER BY id desc LIMIT?($page-1)*$pagesize?AS t2?
WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT?$pagesize;
對limit分頁問題的性能優化方法
MySQL可以利用表的覆蓋索引來加速分頁查詢。
利用了索引查詢的語句中如果只包含了那個索引列(覆蓋索引),那么這種情況會查詢很快。
因為利用索引查找有優化算法,且數據就在查詢索引上面,不用再去找相關的數據地址了,這樣節省了很多時間。另外Mysql中也有相關的索引緩存,在并發高的時候利用緩存就效果更好了。
如果我們也要查詢所有列,有兩種方法,一種是id>=的形式,另一種就是利用join,看下實際情況:
SELECT?*?FROM?product?WHERE?ID?>?=(select?id?from?product?limit?866613,?1)?limit?20
查詢時間為0.2秒!
另一種寫法
SELECT?*?FROM?product?a?JOIN?(select?id?from?product?limit?866613,?20)?b?ON?a.ID?=?b.id;(測試出來查不到相應的ID,而且時間也不快,查詢索引ID的查詢語句中是否需要加一個ORDER BY ID ASC)
查詢時間也很短!
參考文章:MySQL大數據量分頁查詢方法及其優化
總結
以上是生活随笔為你收集整理的不同数据库分页查询的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RF射频卡的介绍与与手机NFC的通信
- 下一篇: Eclipse添加代码自动补全+对齐功能