台灣最大程式設計社群網站
線上人數
690
 
會員總數:245248
討論主題:189105
歡迎您免費加入會員
討論區列表 >> ASP.NET >> 請問有關開啟頁面時,一次載入數千筆資料的效能問題
[]  
[我要回覆]
1
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
請問有關開啟頁面時,一次載入數千筆資料的效能問題
價值 : 30 QP  點閱數:11981 回應數:10

樓主

Stephen Wu
高級專家
7424 113
5959 1237
發送站內信

大家好,
小弟想請問一下,
小弟日前維護的舊系統,和目前新開發的系統,裡面各支程式的第一頁,
都是有提供使用者輸入關鍵字的資料搜尋功能(資料庫的「%」模糊比對),
並在頁面上有一個 GridView 用來呈現結果。

舊系統都是在頁面一載入時,不論資料庫有幾千筆、幾萬筆資料,都是一股腦就全部撈出到 GridView,
導致頁面效能很不好,每點一次都要等個老半天。

目前開發的新系統,希望做到頁面第一次載入時,只撈取前 50 筆資料;
後續的操作(Postback),才一次全撈出,或依使用者輸入的搜尋關鍵字去撈:

但如上述寫法,雖然頁面第一次載入時,可只撈 50 筆,
但只要一去點選 GridView 的頁碼(亦即換頁),就因頁面已 Postback,又變成全撈出,
感覺起來很奇怪。

小弟我曾想在
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{}
中去判斷頁面是否為第一次截入,但沒成功。

能否請問有相關經驗的大大,你們遇到這類情況時,一般都會怎麼做?
先謝謝了。

搜尋相關Tags的文章: [ 效能 ] ,
本篇文章發表於2007-09-14 10:22
== 簽名檔 ==


別忘捐VP感謝幫助你的人 新手會員瞧一瞧
1樓
不錯的參考

maduka
捐贈 VP 給 maduka 檢舉此回應
若是您將上列的程式放在Page_Load之中
就會發生postback之後,就全部撈出來的情形
把程式碼放置的地方調整一下吧
本篇文章回覆於2007-09-14 10:30
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
2樓
不錯的參考

Dreamyi
捐贈 VP 給 Dreamyi 檢舉此回應
基本上在網頁一次呈現上千筆資料就是一種不對的做法,你的效能瓶頸不是卡在資料庫或是 Web Server,而是在於瀏覽器,瀏覽器會把您撈到的資料一筆一筆描繪呈現在 USER 面前,資料量那麼大,瀏覽器當然呈現的很慢,換個方向說,USER 也不需要一次看那麼大量的資料,您一次秀 1000 筆就好,他就看得很花了,其實比較正確的做法,您要在撈資料庫時就盡量篩選資料,這樣也可以減輕 Server 的負擔,我的做法是撈資料都會有一個時間的區間,USER 真的要看很久前的資料時也可以自己選時間,給您參考看看。
本篇文章回覆於2007-09-14 12:04
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
3樓
最有價值解答

小毅
捐贈 VP 給 neweclipse 檢舉此回應
其實沒有什麼好奇怪的,因為樓主你就是這樣寫的
第一次載入時執行"SELECT TOP 50 欄位1,欄位2 FROM 資料表" (只撈50筆)
之後的PostBack(點擊分頁頁碼)執行"SELECT 欄位1,欄位2 FROM 資料表" (全撈後分頁)

GridView內建的分頁功能是把資料全撈回來塞進dataset,之後再做分頁呈現
資料筆數一多,自然出現效能上的問題,自己寫Stored Procedure做分頁就行了

這個Stored Procedure以前貼過一次,效能不錯的說~


分頁的Stored Procedure還有另一種寫法,就是把table的PK insert到一個具有遞增欄位PK的暫存table
依據此暫存table的PK做分頁,不過,實驗證明,效能差很多,所以我就不貼了~
本篇文章回覆於2007-09-14 12:57
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
4樓
作者回應

Stephen Wu
檢舉此回應
感謝各位的回應。

是否還有其他大大能提供任何寶貴意見?
請不吝賜教,
即使只是純粹一兩句的觀念也懇請提供,
謝謝。


本想學舊系統的寫法,頁面載入時都一次全撈出來,
反正等到客戶累積到幾千上萬筆資料時,案子早結案了。
不過還是餅持程式員的良心,調整一下好了。
本篇文章回覆於2007-09-14 22:10
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
5樓
不錯的參考

ALin
捐贈 VP 給 ALin 檢舉此回應
看你那麼有良心的份兒上
幫你挖出了篇文章
請參考
http://www.blueshop.com.tw/board/show.asp?subcde=BRD20050216141103C3Y&fumcde=FUM20041006161839LRJ
本篇文章回覆於2007-09-15 00:55
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
6樓
回應

ALin
捐贈 VP 給 ALin 檢舉此回應
有圖的看這篇
http://blog.sina.com.tw/4907/article.php?pbgid=4907&entryid=3921
本篇文章回覆於2007-09-15 00:57
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
7樓
作者回應

Stephen Wu
檢舉此回應
感謝大家的回應。

若用 GridView 及其分頁功能,而不是自己手動做分頁,
要再搭配上搜尋功能,似乎要在很多執行點上去做判斷。小弟之前想問的是這個。

之前的問題,是卡在說,用 GridView 及其預設的換頁(分頁)功能。
是希望頁面一載入時只撈 50 筆(Top 50);
若使用者按下「查詢」Button時,且未在 TextBox 輸入搜尋關鍵字,就把幾千筆資料全撈出(GridView預設的做法)。

但這樣做會變成,頁面一載入時因只撈 50 筆,GridView 的頁數只有 5 頁,
但只要使用者一點選 GridView 的排序、GridView 的換頁,或沒輸入關鍵字就按「查詢」Button,
因為又變成了幾千筆資料全撈,
等切到第 2 頁時,GridView 的頁碼,會變成上百頁,
因此操作起來有點奇怪。

不過小弟在日前天瓏上架的 ASP.NET AJAX IN ACTION (Manning出版社),
看到可用的範例,該書作者,是在 GridView 的
GridView1_PageIndexChanged()、GridView_Sorted()、查詢Button的 Click()函數,
都去呼叫一個自己寫的函數,
這個函數會判斷使用者有沒輸入搜尋用的關鍵字,並會把輸入的關鍵字,
當作 SqlDataSource 的 FilterExpression,去做資料庫的模糊查詢。


有興趣的人,可去 Manning 出版社的網站,下載那本書的程式碼,
第六章的「GridViewFilter.aspx、GridViewFilter.aspx.cs」。

---------------------
感謝樓上各位大大的資源。若有其他大大有做過類似的功能,若有更好的提議,
歡迎提出討論。本討論串將在兩日後結案,並分配微薄的點數給各大大們。

本篇文章回覆於2007-09-16 23:26
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
8樓
不錯的參考

Dreamyi
捐贈 VP 給 Dreamyi 檢舉此回應
不好意思,我再提供一點點意見:
其實 #7 的做法還是很耗資料庫及 Web Server 的資源,因為 SqlDataSource 的 FilterExpression 及 GridView 的 SortExpression 他們的篩選資料及排序的原理是利用撈出來的 DataTable 的 DataView 來做排序及篩選,也就是說您還是把幾千、幾萬筆的資料先撈出來,再做篩選及排序,關於這方面您可以研究一下 DataView 的 RowFilter 及 Sort 方法,你的做法只解決了溪老師所說的 DataGrid 控制項層的問題,個人還是比較建議從資料庫撈資料時就要盡力篩選資料。
本篇文章回覆於2007-09-17 08:15
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
9樓
作者回應

Stephen Wu
檢舉此回應
您好,
目前小弟我打算暫時先撐著的做法,是如那個書上的範例,各自在
GridView1_PageIndexChanged()、GridView1_Sorted()、查詢Button的 Click()函數,
這三個地方,都去呼叫一個自己寫的函數,
但這個函數都是塞,只撈 50 筆資料:
SqlDataSource1.SelectCommand = "SELECT TOP 50 欄位1,欄位2,欄位n FROM 資料表";

而不用 SqlDataSource1.FilterExpression,
這樣應該就能在第一時間,在資料庫層就只撈 50 筆了吧。
本篇文章回覆於2007-09-17 09:04
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
10樓
不錯的參考

Jeff
捐贈 VP 給 Jeff 檢舉此回應
假設 GirdView 分頁取50筆資料,我的作法如下

1.「第一頁」依條件(或無條件)取得50筆資料,並暫存在 Server 端;並記錄最後一筆的 DataRow 主鍵值(例如編號=50)。
2.執行「下一頁」時,則在 SQL 語法中加入「主鍵索>目前最末筆的主鍵值」子條件,以取得下50筆資料。
並將這新的50筆與之前暫存的50筆合併。
3.若執行「第N頁」,則取「N-目前頁數」的筆數( TopNum=(N-目前頁數)*50 ),再將取得的資料合併。
4.執行「上一頁」或已暫存的頁面,則直接使用暫存的資料顯示在 GridView。
本篇文章回覆於2007-09-17 11:43
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
   
1

回覆
如要回應,請先登入.