1. 程式人生 > >sqlserver中使用row_number進行分頁,效率很高!速度很快!

sqlserver中使用row_number進行分頁,效率很高!速度很快!

                  最近,童鞋要做一個分頁,資料量很大,幾十萬條資料,更坑爹的是,還是要經過表連線進行查詢,速度慢得像烏龜!!

                 怎麼進行優化,可以讓邏輯更清晰,效率更高呢?我試探的過程大概分為以下幾個步驟:

              1.首先因為要進行多張表連線,所以在資料庫中先做了一個檢視,把表連線起來。(但是這樣查詢速度和直接在sql語句中寫表連線差不多,但是如果把表連線寫在檢視中,程式中的sql語句將變得簡潔,思路更清晰)

建立檢視的sql語句如下:檢視名為searchJCR

SELECT     dbo.JCR_Table.JournalID, dbo.JCR_Table.JournalFullTitle, dbo.JCR_Table.JournalISOTitle, dbo.JCR_Table.JournalJCRTitle, 
                      dbo.JCR_Table.JournalISSN, dbo.JCR_Table.JournalLanguage, dbo.JCR_Table.JournalUpdateYear, dbo.SubjectCategories.TotalJouranls, 
                      dbo.SubjectCategories.JournalRank, dbo.SubjectCategories.JournalQuartile, dbo.JCRCategory_Table.CategoriesEName, 
                      dbo.JCRCategory_Table.CategoriesCName, dbo.JCRIF_Table.YearNum, dbo.JCRIF_Table.IFScore, dbo.JCRCategory_Table.CategoriesID
FROM         dbo.JCR_Table INNER JOIN
                      dbo.JCRIF_Table ON dbo.JCR_Table.JournalID = dbo.JCRIF_Table.JournalID INNER JOIN
                      dbo.SubjectCategories ON dbo.JCR_Table.JournalID = dbo.SubjectCategories.JournalID AND 
                      dbo.SubjectCategories.YearNum = dbo.JCRIF_Table.YearNum INNER JOIN
                      dbo.JCRCategory_Table ON dbo.SubjectCategories.CategoriesID = dbo.JCRCategory_Table.CategoriesID
                           2.然後再程式中使用傳統方法進行分頁。
這時候出現了一個問題,使用的檢視查詢出來的結果又很多JournalID重複的記錄,這樣使用JournalID進行分頁就不可行了。所以需要做的就是為每一條查詢記錄指定唯一一個標識,在oracle中有偽列rowid,可以用於區分每一條記錄,在sql server2005之前,沒有辦法區分,但是在sql2005之後,提供了一個ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN)函式用於實現類似於偽列的效果。

                        3.然後在程式中使用row_number()over

()進行分頁。語句如下

select top 20 * from (select row_number()over(order by YearNum DESC,JournalID ASC) as rowid,sJCR.* from searchJCR as sJCR)where rowid not in(select top 20*queryPage  rowid from (select row_number()over(order by YearNum DESC,JournalID ASC) as rowid,sJCR1.* from searchJCR as sJCR1) where 1=1 and ...) and 1=1 and... order by YearNumDESC,JournalID ASC

with t_rowtable  
as
(
    select row_number()over(order by YearNum DESC,JournalID ASC) as row_number,* from [JournalDB].[dbo].[searchJCR] where 1=1

)
select * from t_rowtable where row_number>100
 and row_number <= 60000

row_number函式的用途是非常廣泛,這個函式的功能是為查詢出來的每一行記錄生成一個序號,生成的機制是,按over(排序條件)中的排序條件對每條記錄順序生成一個rowid,然後將記錄按select的order by順序顯示出來。其中“where row_number>100
 and row_number <= 60000
” 可以用來控制每頁的顯示的記錄,可以用來分頁,“where row_number>(page-1)*pageSize
 and row_number <= page*pageSize
”,並且只需要將篩選記錄的條件拼接在where 1=1之後,這樣即使上十幾萬的資料都可以在3s中之內查詢出來,效率很高。例如:

row_number列是由row_number函式生成的序號列。在使用row_number函式是要使用over子句選擇對某一列進行排序,然後才能生成序號。

    實際上,row_number函式生成序號的基本原理是先使用over子句中的排序語句對記錄進行排序,然後按著這個順序生成序號。over子句中的order by子句與SQL語句中的order by子句沒有任何關係,這兩處的order by 可以完全不同,如下面的SQL語句所示:

select row_number() over(order by field2 descas row_number,* from t_table order by field1 desc

    上面的SQL語句的查詢結果如圖所示。


另外要注意的是,如果將row_number函式用於分頁處理,over子句中的order by 與排序記錄的order by 應相同,否則生成的序號可能不是有續的。