最近在做一個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)進行分組時,如果採用第三種方案,每一次分頁都將會進行兩次分組查詢,非常的低效,這個時候,採用第一、二中方案就比較理想。 第三種方案是我比較欣賞的風格:優雅。之所以這麼說,是因為該方案封裝在預存程序中,利用了預存程序編譯後啟動並執行高效性;同時方案本身採用了優雅的通用資料庫技術,通用性和效率都能得到保證。 具體採用什麼樣的方案,一般應該根據自己的項目實際情況來定。如果資料量比較小,建議採用第一種方案;如果資料量中等,採用第二種;反之,第三種是在處理大容量資料分頁查詢下的理想方案。