JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » .Net Framework » .NET Web Tech: Webform ,.net MVC  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to postflat modego to previous topicgo to next topic
本主題所含的標籤
無標籤
作者 Re:ASP.NET 學習資源 [Re:je]
je





發文: 112
積分: 2
於 2011-09-02 01:10 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
WebForm 初學者必讀 - SqlDataSource 做的「分頁」是假分頁

以下是多間上市公司的資訊部門、Java 高手轉學 ASP.NET 都可能會疏忽的問題,因繁體中文書籍有提到的極少。結果導致公司的 ASP.NET「分頁、排序」時效能極差、吃記憶體超驚人、動不動網站掛點、一個關鍵字查詢要 10 幾秒,老闆和主管於是就覺得 ASP.NET 或 SQL Server 效能不佳、只適合小型網站,甚至讓公司其他 IT 人員如 DBA 揹黑鍋。

註: 以下提的「分頁」是指「撈資料」的方式,而非前端 User Interface 頁碼列的第 n 筆、上一筆或下一筆的「前端」呈現的分頁。 很多網路文章和書籍,把二者混為一談,但二者完全是兩碼子事。

-------------------------------------------------------------

故事緣起

ASP.NET 2.0 開始,提供了 SqlDataSource 控制項,讓初學者在 GridView/ListView 可快速寫出「分頁」功能,殊不知這樣撈資料,是在每一次「換頁」或「排序」時,都把符合 SELECT WHERE 條件的資料,全部重撈一遍 (如: 100 萬筆),而不是只撈出畫面上那一頁「真正需要的」資料筆數 (如: 10 筆)。 以下列 SQL 陳述式為例:

SELECT * FROM employees WHERE age > 20

若符合的資料有 100 萬筆,若您用的是 SqlDataSource 控制項,或直接指派 DataTable/DataSet 給 GridView,如下:

GridView1.DataSourceID = SqlDataSource1
GridView1.DataSource = DataTable1

則是公司未來災難的開始。 因為若符合 SELECT WHERE 條件的有 100 萬筆,則當 GridView/ListView 在使用者每次「換頁」或「排序」時,就是把這 100 萬筆全部重撈一次,且資料會全部暫存在 Web Server 主機的記憶體中。當上線人數越多,或資料表未來累積的資料量越多,後果就是,輕者造成查詢速度極慢、客戶或使用者抱怨連連,重者很可能把公司的網站搞掛、造成企業營運損失。

相關文章:

(1) 關於 ASP.NET 網頁的資料分頁效率問題 - 重要喔!! (作者: 章立民)
http://blog.xuite.net/alwaysfuturevision/liminzhang/18396462

(2) 當 DataGrid 遇見 100 萬筆資料 (作者: 聖殿祭司-奚江華,有詳述上述情況)
http://blog.sina.com.tw/dotnet/article.php?pbgid=4907&entryid=3921

解決之道,是當有「分頁」需求時,請不要再用 SqlDataSource 控制項,請務必改用 ObjectDataSource 控制項,並啟用其預設未啟用的 EnablePaging 屬性 :
http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.objectdatasource.enablepaging(v=VS.80).aspx

亦即改以 ObjectDataSource 控制項當作 GridView/ListView 的資料來源,這樣當在換頁或排序時,即可只撈出畫面上「真正要呈現」的資料筆數,如: 10 筆,而非 100 萬筆。

若用的是 SQL Server 2005/2008 資料庫,還可搭配資料庫內建的高效能 RowNumber 函數,來自己手動撰碼,處理分頁問題。

-------------------------------------------------------------

為何很多人不知道這件事? 導致從一些中小企業,到很多上市公司的資訊部門常常寫出效能超差、常常耗盡記憶體的 ASP.NET 網站?

* 早年 ASP 時代,這些「分頁」撈資料的細節,要程式員自己手動處理,一直到了 ASP.NET 1.x 時代也一樣。 但從 ASP.NET 2.0 時代開始,有了 SqlDataSource 控制項出現,大家還以為手動拉一拉控制項,系統就很聰明地自己做好分頁了 (只是表面上的假分頁)。

* 市面上提到此一分頁問題的繁體中文書籍極少。
根據小的我自己觀察,目前只看到兩本繁體中文書有提到,且有直接在書中提供解決方案和程式碼 (若有遺漏請見諒),如下:

(1) 用實例學 ASP.NET 3.5 基礎篇 (作者: 章立民)
http://www.tenlong.com.tw/items/9861814558?item_id=44584

(2) 極意之道─次世代 .NET Framework 3.5 資料庫開發聖典 ASP.NET 篇 (作者: 黃忠成)
http://www.tenlong.com.tw/items/9862011173?item_id=43110

若各位看倌貴人事忙,懶得看本文後半段或自己研究,我個人建議,找第一本章立民先生書上的例子來套用。

另市面上有一些書籍,也常提到「分頁」,不過是指前端 UI 頁碼列的呈現方式 (上一頁、下一頁、第 n 頁、...),和本文提的從資料庫「撈資料」的分頁是完全兩碼子事,勿混為一談。

-------------------------------------------------------------

若用的不是 SQL Server 資料庫,或用的是 SQL Server 2000 或更早版本的資料庫,怎麼辦?

不論您的 ASP.NET 用的是哪一種資料庫,都能搭配 ObjectDataSource 控制項來處理「分頁」,只不過後端資料庫在撈資料時,您要自己用不同的處理方式、演算法來撰碼處理分頁。

* SQL Server 2005/2008 可使用內建高效能的 RowNumber 函數,若能搭配 Stored Procedure 效能更佳。

* 若您用的是 LINQ to SQL,預設在背後用的就是 SQL Server 2005/2008 的 RowNumber 函數來處理分頁。

* SQL Server 2000、Sybase 或他牌資料庫,若 SQL 語法支援 TOP 關鍵字,可用最常見的 SELECT 雙 TOP 夾擊來處理,或 Temp Table ...等不同做法。

* Oracle 資料庫的 Stored Procedure「預設」只能回傳單一值,無法像 SQL Server 能回傳二維的資料內容,可考慮自己寫 C#/VB.NET 的 Class 來取代 Stored Procedure 的功能。

* 他牌資料庫 SQL 語法關鍵字,或特殊解法。大陸或國外討論這種「分頁」演算法的文章非常多,隨便搜尋就有上百篇 Blog 在討論「分頁」的技巧或演算法,有興趣深入研究者可自行搜尋「分页 + ObjectDataSource 控件」等關鍵字。 本文下方會提供其中幾篇超連結。

-------------------------------------------------------------

相關文章或範例下載 (不分繁體、簡體中文):

* [SQL Server] 幾種分頁(Paging) 寫法
http://www.dotblogs.com.tw/jimmyyu/archive/2009/11/09/11499.aspx

* 用 ObjectDataSource 來處理分頁效率
http://bibby.be/2008/11/objectdatasource.html
http://kingjoy1235.pixnet.net/blog/post/31323524-%5Basp.net%5D-%E7%94%A8objectdatasource%E4%BE%86%E8%99%95%E7%90%86%E5%88%86%E9%A0%81%E6%95%88%E7%8E%87

* SQL Server Data Paging 的方式
http://www.dotblogs.com.tw/rainmaker/archive/2009/12/31/12749.aspx

* 自己編寫的 objectDataSource 配合 GridView 實現分頁
http://lncl.blog.hexun.com.tw/28885966_d.html

* ASP.NET 数据分页:
http://www.cnblogs.com/WizardWu/archive/2008/08/02/1258832.html
http://www.cnblogs.com/WizardWu/archive/2008/08/06/1261589.html
http://www.cnblogs.com/WizardWu/archive/2008/09/28/1301616.html

* 使用 Gridview 和 ObjectDataSource 轻松实现自定义分页
http://www.cnblogs.com/taewind/archive/2006/12/12/589131.html

* ASP.NET学习笔记:使用 GridView 和 ObjectDataSource 实现真分页
http://space.itpub.net/12639172/viewspace-510149

* [SQL 2000] 如何取得已知資料集合 特定筆數
http://www.dotblogs.com.tw/hatelove/archive/2009/07/14/9482.aspx

* DataList 分頁 (運用 T-SQL Paging)
http://www.dotblogs.com.tw/hunterpo/archive/2010/01/25/13295.aspx

* 利用 LINQ to SQL 對資料做分頁時應注意的事
http://blog.miniasp.com/post/2009/06/The-important-LINQ-to-SQL-Paging-issues.aspx
http://www.cnblogs.com/wintersun/archive/2009/10/06/1578401.html

-------------------------------------------------------------

網路上流傳的數百篇分頁演算法、SQL 語法和技巧 (簡體中文):

內容太多,小的我只貼其中幾篇:

* 通用存储过程分页
http://www.cnblogs.com/jiangrod/archive/2010/03/17/1687841.html

* 老生常谈,关于分页的问题 (SELECT 雙 TOP 夾擊)
http://topic.csdn.net/u/20090416/15/FFD0CC76-3ECE-4D86-B952-F1702C8887F0.html

* oracle sql 分页
http://www.cnblogs.com/xsmhero/archive/2011/08/01/2124239.html

* 浅淡SqlServer的Top与Oracle的RowNum
http://www.cnblogs.com/liguangxi8/archive/2010/05/21/1740708.html

* .Net通用分页类 (存储过程分页版,完全自定义显示样式,包括中英显示)
http://www.cnblogs.com/84ww/archive/2008/08/02/1258744.html

* Sql 2000 分页效率之我见
http://www.cnblogs.com/newsea/archive/2009/08/22/1552214.html

* 2分法-通用存储过程分页(top max模式)版本 (性能相对之前的 not in 版本极大提高)
http://www.cnblogs.com/hertcloud/archive/2005/12/21/301327.html
http://www.cnblogs.com/jitian/archive/2011/03/22/1991961.html

* 分享一个分页存储过程和分页函数
http://www.cnblogs.com/cyan/archive/2010/01/14/1648043.html

* 千万级数据的分页通用存储过程
http://www.cnblogs.com/caojinqin/archive/2010/03/09/1681544.html

* 高效分页存储过程
http://www.cnblogs.com/immensity/archive/2010/04/08/1707298.html

* Sqlserver 分页的总结
http://www.cnblogs.com/duanseven/archive/2010/07/05/1771722.html

* 高效的二分法TOP MAX/TOP MIN分页存贮过程
http://www.cnblogs.com/livexy/archive/2010/08/19/1771931.html

* 分页查询 SQL 语句
http://www.cnblogs.com/aito/archive/2010/08/27/1810494.html

* 毫秒级百万数据分页存储过程
http://www.cnblogs.com/im531/archive/2010/11/26/1888490.html

* 再上数据分页控件(不用 Stored Procedure)
http://www.cnblogs.com/huyong/archive/2011/04/04/2005204.html

* 用 DataReader 高效率做 SQL Server 2000 分页
http://www.cnblogs.com/caizhiyuan/archive/2011/04/26/2029109.html

* 证明 DataReader 做 GridView 分页的可行性
http://www.cnblogs.com/luchaoshuai/archive/2011/04/27/2029937.html

* 分页:所有的数据绑定控件都可以用的
http://www.cnblogs.com/yangzhixiao/archive/2011/07/15/2107145.html

-------------------------------------------------------------

其他

* FormView、DetailsView 控制項也一樣,雖然預設內建分頁功能、頁碼列,也都支援直接以 SqlDataSource 控制項或 DataTable/DataSet 物件當作資料來源,可快速實作出分頁程式,但會面臨和本文前述一樣的問題。因此應視情況,改用 ObjectDataSource 控制項才是正道。

* SqlDataSource 控制項並非該完全禁用,而是看情況使用。若是不用「分頁;換頁」的功能,如只是要當作某個下拉選單 DropDownList 的資料來源,就很適合用 SqlDataSource 控制項。

-------------------------------------------------------------
-------------------------------------------------------------

以上,僅提供初學 WebForm 者參考。

至於其他有關效能的議題,如: 資料庫索引建得不適當、SQL 陳述式撰寫不佳導致無法正確使用索引來查詢,則不在本文討論範圍。

-------------------------------------------------------------


reply to postreply to post
臉書「資料庫之道」粉絲團:
http://www.facebook.com/DBtaoist
話題樹型展開
人氣 標題 作者 字數 發文時間
4909 ASP.NET 學習資源 je 2489 2011-08-29 01:12
4154 Re:ASP.NET 學習資源 yahoo1234tw 20 2011-08-29 21:19
4151 Re:ASP.NET 學習資源 je 574 2011-08-30 00:50
4217 Re:ASP.NET 學習資源 je 704 2011-08-30 00:51
4401 Re:ASP.NET 學習資源 je 7200 2011-09-02 01:10
» JWorld@TW »  .Net Framework » .NET Web Tech: Webform ,.net MVC

reply to postflat modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8