国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

利用自定義分頁技術提高數據庫性能

2024-07-21 02:32:05
字體:
來源:轉載
供稿:網友

Web應用程序是顯示數據庫中數據的一個非常好的方法,通過它,你可以把業務復雜,并有訪問和安全規則的數據庫數據以一種簡單、直觀的方式向用戶提供查詢和更新的功能。用戶判斷數據庫應用程序一個很常用的標準就是處理數據的快慢。許多Web頁面都向用戶提供了多種可搜索的列表顯示來有效地定位記錄的位置,一個比較簡單而且常用的例子就是在線圖書查詢系統,它允許用戶可以按作者,按書名或者按主題來檢索圖書信息。
    asp.net提供了一個DataGrid控件可以比以前的ASP方便地創建創建數據列表,DataGrid控件除了內建的數據表現和方法之外,還允許用戶自己定義表現形式。分頁技術為用戶可管理的數據查找提供方便。DataGrid內建的分頁技術很容易實現,但數據量很大時,它的方便性是以犧牲性能為代價的。下面,我們就看看如何通過自定義的分頁方法來實現快速處理大量數據的結果集的辦法。我們這里討論的方法比DataGrid的默認分頁方法是快速和更加有效的,這是因為每次請求不需要把全部的數據結果發送到Web服務器。相反,它只需要發送每個頁面需要的那些數據集。例如:如果一個用戶只要求100個頁面中每頁顯示25條記錄的第4頁的結果集,服務器只需要發送第75-100行的數據即可,而不是1-1000行的完全數據。默認的傳送方式如圖1所示:


    從圖中可以看出,DataGrid的內建分頁方法是效率不高的,每次請求都必須把整個查詢結果發送給Web服務器,Web服務器再把數據分成相應的頁面。利用DataGrid的內建的分頁方法盡管是很簡單的,但是,由于Web應用的無序性特征,一個用戶每次從一個頁面轉向另外一個頁面時,DataGrid對象都被銷毀并重新創建,這就意味著數據庫服務器每次都必須發送全部的結果集。
    自定義的分頁方法只返回所要檢索的那些結果集,如下圖2所示:

    從上面的圖中可以看到,數據庫每次只需要返回所要顯示的數據記錄。首先,我們在數據庫中建立一個存儲過程,并有兩個輸入參數,分別是要返回數據的第一條記錄數和最后一條記錄數,在SQL Server7.0以上的版本中,都有一個top關鍵字限制返回到結果集中的前多少條記錄數,然而不幸的是,沒有一個方法可以返回中間一部分的數據,例如第75條記錄到100條記錄的數據。Oracle中有一個rownum()的擴展函數可以返回中間的記錄,比如:"select * form Authors where Author_Last_Name = 'Anderson' and rownum() >=75 and rownum() <= 100"。然而,由于Oracle是在排序之前指定rownum的值,因此,這樣的查詢"select * from Authors where rownum <= 25 order by Author_Last_Name"將得不到我們期望的結果。我們下面所講的方法是針對SQL Server的,但這里的概念對適合Oracle開發人員也是適用的。
    要創建一個返回指定條記錄結果的存儲過程,首先必須指定返回結果集的條記錄數,可以用臨時表,也可以用table變量(SQL Server 2000),兩個在性能上沒有太大的差別,但是,table變量是存儲在內存中的,如果你的服務器內存不多的話,可以考慮用臨時表,臨時表使用硬盤存儲結果,臨時表需要手工釋放對象,而table變量在存儲過程結束后自動釋放。

    下面就是我們要創建的存儲過程:

create PRoc GetAuthors
@Author_Last_Name as varchar(100) = null,
@StartRow as int = null,
@StopRow as int = null
AS

---- 建立有標識符列的table變量
declare @t_table table
(
[rownum] [int] IDENTITY (1, 1) Primary key NOT NULL ,
[Author_Last_Name] [varchar] (40) ,
[Author_First_Name] [varchar] (20) ,
[phone] [char] (12) ,
[address] [varchar] (40) ,
[city] [varchar] (20) ,
[state] [char] (2) ,
[zip] [char] (5)
)

---- 在返回指定的@StopRow行數之后停止處理查詢
Set RowCount @StopRow

---- 插入到table變量中
insert @t_table
(
[Author_Last_Name],[Author_First_Name],[phone],[address],[city],[state],[zip]
)
SELECT [Author_Last_Name],[Author_First_Name],[phone],[address],[city],[state],[zip]

FROM authors
WHERE Author_Last_Name like '%' + @Author_Last_Name + '%'
ORDER BY Author_Last_Name

---- 返回到正確的結果
SELECT * FROM @t_table WHERE rownum >= @StartRow
ORDER BY rownum

GO

    參數@StartRow和@StopRow接收整數值,代表要返回的開始記錄和結束記錄,如果要在一個25條記錄的頁面中返回第4頁,我們就可以設置@StartRow為76,@StopRow為100。我們在table變量@t_table中定義了一個叫rownum的整數類型的列,并指定為標識符列,這個列在我們這里介紹的分頁技術中是很重要的,當我們插入數據時,這個列自動增加,它將在插入數據時起排序作用。SET ROWCOUNT語句對優化性能很關鍵,它告訴SQL Server進行限制要插入的數據,如果我們要76-100條記錄之間的數據,那么就可以不必插入大于100條記錄的數據。最后的SQL語句從@t_table的table變量選擇rownum大于或者等于@StartRow的那些數據集,然后把它們返回到Web服務器,由Web服務器綁定到DataGrid對象。值得注意的是:如果要得到76到100條記錄的數據,我們必須往table變量中插入100條記錄的數據,這意味著:如果瀏覽者請求的頁數越來越大,頁面性能也會有所下降的。例如:要顯示第100頁的數據(從第2451條記錄到第2500條記錄),我們必須先向table變量或者臨時表填充2500條記錄,因此,性能依賴于你計算機的硬件和你要返回的記錄數,有測試表明,在SQL Server 2000中使用這樣的存儲過程平均在200-250毫秒內返回第100頁,而返回第一頁只需要4毫秒。即使返回第500頁的數據(從第12451到12500條記錄)也可以在650到750毫秒內完成。應該說這種情況是很少見到的。 但為了減輕數據庫和網絡傳輸的壓力,設計合理的查詢結果頁數是很見效的。

    現在,我們寫好了一個存儲過程來做分頁的工作,而不是用Web服務器來做這個事情,我們接下來要做的就是為DataGrid對象編寫代碼來使用我們的分頁技巧。DataGrid的AllowPaging、AllowCustomPaging、PageStyle屬性有助于避免我們編寫自己的代碼來跟蹤記錄瀏覽者目前在哪一個頁面訪問和都請求過哪些頁面。我們應當設定AllowCustomPaging為True,否則,在你使用DataReader或者SQLDataReader綁定到DataGrid對象會遇到麻煩。在任何可能的情況下,應當盡量使用SQLDataReader而不要使用DataSet來裝載DataGrid對象。據性能測試表明:在構建列表顯示數據時,使用SQLDataReader比使用DataSet要快兩倍以上。不要設定AllowPaging和PageStyle的值,這是因為,如果使用這兩個屬性,你必須在viewstate中維護DataGrid,但為了追求性能最佳化,我們必須設定DataGrid的EnableViewState屬性為false,盡管這樣我們自己必須編寫一點代碼來實現我們的分頁,但是性能會有所提高的,因為在每次與Web服務器打交道時不必再在viewstate中存儲內容了。

   一旦我們關閉了DataGrid自己在viewstate中保存的能力,我們就必須自己編寫代碼來實現用戶從一頁導航到另一頁。DataGrid如果自己不在viewstate中進行保存,那么它也不再跟蹤記錄“前一頁”和“下一頁”是哪些頁面了。我們自己添加導航按鈕來幫助瀏覽者進行導航。最簡單的辦法是在頁面上增加兩個按鈕:“上一個”和“下一頁”。要進入到下一頁,我們在“下一頁”按鈕上增加click事件,通過我們的自定義分頁存儲過程請求相應的記錄。例如:如果第一頁由第1條到第25條記錄組成,那么要導航到第二頁,我們就向存儲過程的@StartRow傳遞參數26,向@StopRow傳遞參數50即可,要返回到第一頁,@StartRow和@StopRow分別為1和25。

    下面是使用VB.NET編寫的“下一頁”事件的例子:

Private Sub ButtonNext_Click (ByVal sender As Object, _
ByVal e As System.EventArgs) Handles ButtonNext.Click

viewstate("StartRow") = viewstate("StartRow") + dgrid.PageSize
viewstate("StopRow") = viewstate("StartRow") + dgrid.PageSize

'運行存儲過程,返回SQLDataReader
dgrid.DataSource = RunSprocReturnDR (textAu_lname.Text, _
textAu_fname.Text, viewstate("StartRow"),viewstate("StopRow"))
dgrid.DataBind()

End Sub

    從上面的例子可以看出,我們在viewstate中保存的只是@StartRow和@StopRow的信息,這比在viewstate中保存整個DataGrid對象高效的多。“下一頁”和“上一頁”按鈕提供的只是簡單的導航,要實現更詳細的導航信息,比如:共多少頁、自定義頁面記錄數等,也是可以的,但要記住不要使用DataGrid內建的PagingStyle屬性。根據測試表明,不保存DataGrid會提高性能到54%。
    列表顯示信息的性能對瀏覽者的訪問是很重要的,設計不好的列表顯示會大大降低應用程序的性能,不管它的后端數據庫是多么快速。使用自定義分頁技術,我們可以避免DataGrid默認分頁機制帶來的缺陷,如果要實現可搜索的列表顯示,讓你的用戶感到你的應用程序快速和可擴展,還要編寫更多的代碼,相信各位會編寫出更加優秀的程序的。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 赤水市| 浙江省| 准格尔旗| 海城市| 彭泽县| 怀远县| 佛学| 会东县| 宜丰县| 丹寨县| 大田县| 兴义市| 彭山县| 合作市| 满城县| 富民县| 石首市| 武夷山市| 德州市| 青阳县| 阳高县| 密云县| 镇平县| 翁牛特旗| 清远市| 锡林郭勒盟| 星座| 峡江县| 诸城市| 阿坝县| 苗栗县| 措勤县| 白沙| 惠水县| 舞阳县| 芒康县| 邹城市| 通道| 根河市| 洛阳市| 淮阳县|