程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> 在ASP.NET中實現大結果集分頁

在ASP.NET中實現大結果集分頁

編輯:關於ASP.NET

在Web應用程序中,對一個大數據庫結果集進行分頁已經是一個家喻戶曉的問題了。簡單的說,你不希望所有的查詢數據顯示在一個單獨的頁面中,所以帶有分頁的顯示才是更合適的。雖然在傳統的asp裡這並不是一個簡單的任務,但在asp.net中,DataGrid控件把這一過程簡化為只有幾行代碼。因此,在 asp.net中,分頁很簡單,但是默認的DataGrid分頁事件會從數據庫中把所有的記錄全部讀出來放到asp.net web應用程序中。當你的數據在一百萬以上的時候,這將引起嚴重的性能問題(如果你不相信,你可以在你的應用程序中執行一個查詢,然後在任務管理器中查看 aspnet_wp.exe的內存消耗情況)這也就是為什麼需要自定義分頁行為,這樣可以保證僅獲得當前頁需要的數據記錄。

在網上有很多關於這個問題的文章和帖子,還有一些成熟的解決方案。我寫這篇文章的目的不是向你展示一個可以解決一切問題的存儲過程,而是出於優化已有方法,同時為你提供一個可供測試的應用程序,這樣你就可以根據自己的需要進行開發。

但是我對目前網上介紹的方法不是很滿意。第一,使用了傳統的ADO,很明顯它們是為“古老”的asp而寫的。剩下的一些方法就是SQL Server存儲過程,並且其中的一些由於相應時間過慢而無法使用,正如你在文章最後所看到的性能結果一樣,但是還是有一些引起了我的注意。

通用化

我要對對目前常用的三個方法進行仔細的分析,它們是臨時表(TempTable),動態SQL(DynamicSQL)和行計數 (Rowcount)。在下文中,我更願意把第二個方法稱為(升序-降序)Asc-Desc方法。我不認為動態SQL是一個好名字,因為你也可以把動態 SQL邏輯應用於另一個方法中。所有這些存儲過程的通病在於,你不得不估計哪些列是你即將要排序的,而不僅僅是估計主鍵列(PK Columns)而已,這可能導致一系列的問題——對於每個查詢來說,你需要通過分頁顯示,也就是說對於每不同的排序列你必須有許多不同的分頁查詢,這意味著你要麼給每個排序列做不同的存儲過程(無論使用哪種分頁方法),也麼你必須借助動態SQL的幫助把這個功能放在一個存儲過程中。這兩個方法對於性能有微小的影響,但是它增加了可維護性,特別是當你需要使用這個方法顯示不同的查詢。因此,在本文中我會嘗試使用動態SQL對所有的存儲過程進行歸納,但是由於一些原因,我們只能對實現部分的通用性,因此你還是得為復雜查詢寫獨立的存儲過程。

允許包括主鍵列在內的所有排序字段的第二個問題在於,如果那些列沒有作適當的索引,那麼這些方法一個也幫不上忙。在所有這些方法中,對於一個分頁源必須先做排序,對於大數據表來說,使用非索引列排序的成本是可以忽略不計的。在這種情況下,由於相應時間過長,所有的存儲過程都是無法在實際情況下使用的。(相應的時間各有不同,從幾秒鐘到幾分鐘不等,這要根據表的大小和所要獲得的第一個記錄而定)。其他列的索引會帶來額外的不希望出現的性能問題,例如如果你每天的導入數據很多,它有可能變得很慢。

臨時表

首先,我准備先來說一下臨時表方法,這是一個廣泛被建議使用的解決方案,我在項目中遇到過好幾次了。下面讓我們來看看這個方法的實質:

CREATE TABLE #Temp(
  ID int IDENTITY PRIMARY KEY,
  PK /*heregoesPKtype*/
)
INSERT INTO #Temp SELECT PK FROM Table ORDER BY SortColumn
SELECT... FROM Table JOIN # Temp temp ON Table.PK = temp .PK ORDER BY temp .ID WHERE ID > @StartRow AND ID< @EndRow

通過把所有的行拷貝到臨時表中,我們可以對查詢進一步的優化(SELECT TOP EndRow …),但是關鍵在於最壞情況——一個包含100萬記錄的表就會產生一個100萬條記錄的臨時表。考慮到這樣的情況,再看看上面文章的結果,我決定在我的測試中放棄該方法

升序-降序

這個方法在子查詢中使用默認排序,在主查詢中使用反向排序,原理是這樣的:

DECLARE @temp TABLE(
  PK /* PKType */
  NOT NULL PRIMARY
)
INSERT INTO @temp SELECT TOP @PageSize PK FROM
(
  SELECT TOP(@StartRow + @PageSize )
  PK,
  SortColumn /* If sorting column is defferent from the PK,SortColumn must
  be fetched as well,otherwise just the PK is necessary
  */
  ORDER BY SortColumn
  /*
defaultorder–typicallyASC
  */
)
ORDER BY SortColumn
/*
reversed default order–typicallyDESC
*/
  SELECT... FROM Table JOIN @Temp temp ON Table .PK= temp .PK
  ORDER BY SortColumn
  /*
defaultorder
  */

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved