網站性能越來越差怎么辦?
新的一年,你的老板或客戶,是否曾和你抱怨公司的網站性能愈來愈差?網站大家都會寫,自從有了 Visual Studio 之后,連你家樓下的正妹小喵和隔壁的王大嬸都會寫 ASP.NET。但同樣的一個畫面,背后的性能卻可能是天差地遠,更惶論多人同時上線的企業網站,而程序員的身價也因此有所差別。本帖提供一些改善網站性能的點子,從硬件、軟件、程序技巧的層面都有,也歡迎大家分享自己的經驗或秘技。
(1) 重新調整或重新設計 DB schema、「索引 (index)」
一個在線系統的性能不佳,主要原因都是來自于數據庫規劃及 SQL 語句層面,至于 .NET 程序撰寫不良都還在其次。
先將數據庫適度地做正規化,如:一個 Table 中,避免把常用的字段、很少用的字段,都塞在同一個表中,而影響數據掃描的速度。
應該將很少用的字段,另切割出來成為另一個表。
請參考:
30 分鐘快快樂樂學 SQL Performance Tuning:
http://www.cnblogs.com/WizardWu/archive/2008/10/27/1320055.html
----------------------------------------------
(2) 改寫 SQL 語句,注意 index 是否在查詢時有真的被用到
* 同樣的功能,一個不良的「關聯子查詢」和良好的「獨立子查詢」,之間的 SQL 性能差距,是不到一秒鐘和好幾分鐘以上的差距。
* 一些 SQL 關鍵詞,只要一出現在 SQL 語句中,就可能造成表的「索引 (index)」完全失效或部分失效,變成要整個表去逐行逐列地掃描,
例如: NOT、NOT IN、!=、<>、OR ...等關鍵詞,
還有「LIKE '%關鍵詞'」的模糊查詢,也會造成索引失效,但「LIKE '關鍵詞%'」就不會造成索引失效。
請參考:
30 分鐘快快樂樂學 SQL Performance Tuning:
http://www.cnblogs.com/WizardWu/archive/2008/10/27/1320055.html
----------------------------------------------
(3) 使用 Native 的 DataProvider
放棄 OleDb,改用 ADO.NET Native 的 DataProvider,如: SqlClient、OracleClient。但若您公司堅持要用 Sybase 這種從 2003 年之后,就不曾更新 DB driver 的數據庫,就只好繼續用性能不佳的 OleDb 去聯機了。
據版工我用 Visual Studio 內建的 press test 工具,測試 OleDb 和 SqlClient 的性能差距,仿真 30 人同時上線,用瀏覽器擷取一萬筆數據,兩者的速度就差了一秒鐘;且當數據庫的數據越多,或越多人同時上線時,性能差距會更明顯。
----------------------------------------------
(4) 用程序或軟件做緩存
用程序做緩存,如 ASP.NET 從 1.x 時代,就已內建的 Cache (緩存) 機制;或用一些第三方的輔助軟件、Framework,這方面若有其它網友知道好用的軟件,亦懇請留言告知。
----------------------------------------------
(5) 用硬件做快取或緩沖、砸錢加裝 AP Server
ITHome - 游戲基地網頁效能提升的關鍵人物 (此連結連至臺灣網頁,若無法開啟敬請見諒) :
http://www.ithome.com.tw/itadm/article.php?c=52558
以下引用自原文:
種種缺失使得網站的使用人數銳減。面對網站一堆問題,陳xx也決定要將網站再次大幅度調整,將之前的網頁程序,以及 SQL 查詢語句全部重寫,他們花了三個月的時間執行。
陳xx還在原本的網頁服務器,與數據庫服務器的架構中,加入一組應用程序服務器,作為網頁服務器 cache 數據的來源。
改版之后的新網站,搜尋速度提升許多,先前每日的統計數據中,處理速度超過 3 秒的數據超過 50 萬筆;而改版后,每星期超過 3 秒的查詢不到 10 筆,而這少數反應速度不夠快的查詢,也多是內部作業執行大量批處理導致的。
由于原本使用的 L4 Switch 較為老舊,負載量比較差,因此陳xx選擇將它汰換新的設備,加強負載量;恰好那時正好準備將應用服務器的架構上線,就藉此機會將網絡架構更新。陳xx說,這樣的架構搭配負載較強的 L4 交換器,強化網站的處理性能,并憑借此抵御網絡攻擊。在此之后,網站依然會受到零星攻擊,但都不會對造成太大影響。
----------------------------------------------
(6) 用硬件做快取或緩沖、砸錢加裝 AP Server
數字之墻 - 網站外銷的個人實踐(二)運營 (此連結連至臺灣網頁,若無法開啟敬請見諒) :
http://epaper.pchome.com.tw/adm/brief_left.htm?s_code=0263
以下引用自原文:
全盛時期,來自美國 blog 的流量每天達 80 萬次。這個數字其實不高,對程序高手來說是小菜一碟,但筆者是半吊子工程師,知識有限也因此可能程序寫得不好,頻頻被主機供貨商發信警告,要求改善網站系統性能。最后,我決定開發 cache system。
cache system 緩存系統上線后,將數據庫讀寫,從每天 80 萬次降低到每天 16 萬次。這期間也請高手朋友幫忙進行數據庫結構優化,幫助很大。筆者在過程中學習到,一個良好的「緩存系統 (cache system)」對于提供 Widget 功能的網站來說非常重要。
…中間略…
能夠做到隨時搬遷整個網站到另一家主機供貨商,除了程序本身的調整外,還要歸功于網站管理軟件的盛行。在此要推薦的一套稱為 Plesk 的網站管理軟件。有的主機供貨商會直接幫你安裝 Plesk ,免費或另外付費。 Plesk 的所有管理功能都是透過 Web 界面,方便到無以復加,大大降低對技術能力的要求。
除了 Plesk 以外,網站管理軟件還有其它選擇。還有 WHM 加上 cPanel 的組合,也是常見的網站管理解決方案。不過筆者還是比較偏好使用 Plesk,畢竟使用起來容易,也難怪他們的市場占有率一直是獨大。只是,功力高的工程師可能會喜歡 WHM + cPanel,因為彈性比較大。不論選擇哪一種,都可以幫助你節省許多時間。
----------------------------------------------
(7) 加裝實體機器做 Loading Balance (負載平衡)。一些 Server OS 亦內建此類設定功能。
----------------------------------------------
(8) 程序技巧 - ADO.NET
能用 DataReader 就不要用 DataSet / DataTable,前者讀取速度快又不耗內存;后者雖較有彈性,但速度較慢又會每個使用者消耗許多內存。若您連 DropDownList 控件的數據來源,都用 SqlDataSource 控件的默認值 - DataSet,則當頁面里塞了一堆下拉選單時,當然性能會受影響。
但前提是程序員對 ADO.NET 要有一定程度的了解,若只會用 Visual Studio 透過圖形界面,拖拉 TableAdapter、DataTable、.xsd 就免談了。
若為 DataTable 建立 Primary Key,DataTable 會建立一個索引,追蹤新增到 DataTable 中的數據是否符合此條件約束 (constraint)。ADO.NET 2.0 會使用 algorithm 的「紅黑樹算法 (Red-Black Tree,是一種「平衡樹」算法) 去處理索引,讓 DataTable 的數據量大時,較方便維護索引;但缺點是建立索引時會降低一些性能。
此外,數據庫的走訪和撈值,應該盡量在一次 DB connection 做完,一個 connection 可搭配多個 DbCommand 對象使用,不用每次都一個 DbConnection 配一個 DbCommand。
在此推薦一本不錯的 ADO.NET 原文書:
Programming Microsoft ADO.NET 2.0 Core Reference
http://www.amazon.com/Programming-Microsoft%C2%AE-ADO-NET-Core-Reference/dp/073562206X/ref=sr_1_1?ie=UTF8&s=books&qid=1230971264&sr=1-1
有探討到許多市面上書籍少見的深入內容,像 Oracle + ADO.NET 的各種應用、Connection Pooling 的特性、各種的數據庫 Balk (批次) 作業應用。
請參考:
適時調整 SqlDataSource 控件的 DataSourceMode 屬性:
http://www.cnblogs.com/WizardWu/archive/2008/07/15/1243661.html
使用 ADO.NET 的 NextResult 方法取得多個 Result Set:
http://www.cnblogs.com/WizardWu/archive/2008/07/11/1241174.html
----------------------------------------------
(9) 程序技巧 - .NET 語法
* 避免一些書上教的,把 DataTable 或大量數據,直接塞到 Session,此舉在真正要上線的系統必死無疑。Session 在多人同時上線時,內存的消耗是很可觀的,因為 Session 是每個用戶各存一份在服務器的內存里,而非像「緩存 (cache)」是所有的用戶共享服務器的一塊內存。在很多 ASP.NET 的需求中,可用 ViewState 或 HiddenField 控件取代 Session。
* 能用「泛型 (Generics)」就不要用舊版的寫法,Generics 除了安全外,亦可避免 .NET 類型在 Boxing / Unboxing 轉型時影響性能,例如:
動態數組中,能用 List 就不要用舊的 ArrayList,能用 Dictionary 就不要跑雙層的循環 (loop)。
當然上述前提,是系統要用 .NET 開發,還在靠 ASP 或非 OOP 語言硬撐的舊系統就免談了。
----------------------------------------------
(10) 程序技巧 - 數據庫「事務 (Transaction)」
您是否知道 SQL Server 的默認「事務隔離等級 (Isolation Level)」,是「ReadCommitted」,當您在寫 ADO.NET 用了 SqlTransaction 時,默認是當某個人在修改某一筆記錄時,其它所有讀取這一筆記錄的人,都會被「鎖定 (lock)」住,造成其它全部用戶的瀏覽器都在等待中,無法做其它工作。
而 Oracle 事務的特性,是絕不會有類似無法讀取的情形,至少會用類似 SQL Server 2005 新增的「快照隔離 (Snapshot Isolation)」,讓用戶至少能先讀取到未 Commit 或 Rollback 的記錄,而不用呆坐在瀏覽器前面傻等。
不過 SQL Server 2005 的「快照隔離」默認未啟用。用 SQL Server 開發的系統,若怕用戶被鎖定的問題,可視 project 需求,改用最寬松的「ReadUncommitted」事務隔離等級,其特性為不會造成任何鎖定,但可能會造成 Dirty Read。SQL Server 有下列七種「事務隔離等級」,有興趣的網友可去查詢 ADO.NET 書籍或 MSDN Library:
Chaos
ReadCommitted // SQL Server 默認值
ReadUncommitted // 最寬松,會有 Dirty Read
RepeatableRead
Serializable // 最嚴,會有大量的鎖定
Snapshot
Unspecified
請參考:
Oracle 11g 學習筆記 (5):
http://www.cnblogs.com/WizardWu/archive/2008/12/07/1349665.html
----------------------------------------------
(11) ASP.NET 分頁
GridView + SqlDataSource 的默認行為,就是每次換頁或排序時,不管數據庫有幾筆記錄都全部重撈一次;當數據庫有一百萬筆數據,就在每個用戶換頁時,都一百萬筆全部重撈出來,此舉消耗了大量的 Web server/ AP server 內存、數據庫系統資源、網絡頻寬,結果網站性能可想而知。
很多企業內的小型網站,為了省錢,隨便外包給低價搶標的工作室,或沒經驗的學生和 SOHO 族,可能都因此已經埋下了恐怖的后遺癥。
請參考:
ASP.NET 數據分頁 1 ~ 4 篇 series :
(有現成的 ASP.NET 2.0 + ObjectDataSource 控件 + Stored Procedure 做「分頁」的示例可下載)
http://www.cnblogs.com/WizardWu/archive/2008/09/28/1301616.html
http://www.cnblogs.com/WizardWu/archive/2008/09/07/1286270.html
http://www.cnblogs.com/WizardWu/archive/2008/08/06/1261589.html
http://www.cnblogs.com/WizardWu/archive/2008/08/02/1258832.html
http://blog.sina.com.tw/4907/article.php?pbgid=4907&entryid=3921
----------------------------------------------
(12) Design Patterns
雖然「設計模式」不是為解決性能問題而誕生的,但可適度防止沒經驗的新人做出蠢事。多學一些 .NET 技術敵營注重的系統架構、OOAD、Design Patterns 和相關 Framework,對提升自己的身價和薪資也有幫助。
相關書籍:
C# 3.0 Design Patterns:
http://oreilly.com/catalog/9780596527730/index.html
Head First Design Patterns:
http://oreilly.com/catalog/9780596007126/index.html
----------------------------------------------