DB2的分頁高效率實現總結

最近在做一個DB2的項目,遇到分頁處理的設計時開始犯難。以前一直採用MySQL作爲項目數據庫,其中的Limit關鍵字非常人性化,MySQL把分頁的處理邏輯封裝到了數據庫的核心中,使得做查詢設計時,根本不用過多的考慮分頁的問題。
 
可是DB2卻把這個難題推到了我們面前。其實不止DB2如此,很多大型的數據庫例如MS SQL Server也不支持分頁關鍵字。當然,DB2中提供了RowNumber函數,同Oracle有一些類似。有很多解決方案都是由此關鍵字得來的。
 
爲了解決這個問題,互聯網上提供瞭如下幾個解決方案:
 
方案一:利用JDBC2的數據集。JDBC2數據集中提供了absolute方法,用來在查詢的結果集中進行定位,數據集保存在內存中,你必須告訴JDBC你想定位的絕對位置,這個位置由你來計算。對於海量的數據集,這種方式效率並不高。
 
方案二:利用DB2自帶的函數 ROWNUMBER() OVER(ORDER BY sort-key),這裏的RowNumber函數是通過排序計算出來的行的順序號。根據這個原理,可以先SELECT滿足WHERE條件的所有記錄,然後用ORDER BY排序,在行號的基礎上,結合子查詢的組合得出查詢結果。例如:
select * from ( select rownumber() over(order by foo.bar, foo.baz) as rownumber_, * from foos foo order by foo.bar, foo.baz ) as temp_ where rownumber_ between ?+1 and ?
 
方案三:這個解決方案准確的說是從MSSQL陣營中獲得的。參考以下鏈接:http://dev.csdn.net/author/mengyao/f78b60685f5b483ba459f4962fab6774.html。早先有人給出瞭如何從數據庫中取出從M到N的記錄的解決方案,後來有人寫成了存儲過程,並不斷得到改進和優化。我很欣賞這種不斷鑽研的精神,只有這樣技術才能不斷的得到進步。
 
第三種方案的實現原理其實很簡單。先用一個子查詢從數據庫中選出(Page-1)*PageSize個記錄來,然後用max/min關鍵字(更加排序的方式)取出子查詢中的最大或最小值。外查詢再取出所有滿足大於/小於這個值的前PageSize個記錄。就這麼簡潔。
 
早一些的實現使用了NOT IN/NOT EXIST等關鍵字,後來被MAX/MIN方案所取締,主要是考慮到效率問題。實現者表現出了對於數據庫的精湛技術的同時,也爲我們提供了一個優雅的解決方案。
 
方案比較:
 
三種方案各有所長。
 
第一種方案可以算得上是一種獨立的解決方案,不需要任何特殊的數據庫技術支持,只要使用JDBC2.0就可以。但在處理大規模的數據查詢時,需要耗費大量的數據庫遊標移動所帶來的性能損耗。
 
第二種方案是DB2和Oracle採用的解決方案,相比前一種,性能上要好很多。但同第一種相類似,仍然要把所有滿足條件的記錄放到內存中,通過內部的遊標查詢來實現分頁。在特定於數據庫的方案中,這種方案是一種可取的方案。另外,在對分組查詢(Group BY)進行分組時,如果採用第三種方案,每一次分頁都將會進行兩次分組查詢,非常的低效,這個時候,採用第一、二中方案就比較理想。
 
第三種方案是我比較欣賞的風格:優雅。之所以這麼說,是因爲該方案封裝在存儲過程中,利用了存儲過程編譯後運行的高效性;同時方案本身採用了優雅的通用數據庫技術,通用性和效率都能得到保證。
 
具體採用什麼樣的方案,一般應該根據自己的項目實際情況來定。如果數據量比較小,建議採用第一種方案;如果數據量中等,採用第二種;反之,第三種是在處理大容量數據分頁查詢下的理想方案。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章