新的一年,你的老板或客戶,是否曾和你抱怨公司的網(wǎng)站性能愈來愈差?網(wǎng)站大家都會寫,自從有了 Visual Studio 之后,連你家樓下的正妹小喵和隔壁的王大嬸都會寫 ASP.NET。但同樣的一個畫面,背后的性能卻可能是天差地遠,更惶論多人同時上線的企業(yè)網(wǎng)站,而程序員的身價也因此有所差別。本帖提供一些改善網(wǎng)站性能的點子,從硬件、軟件、程序技巧的層面都有,也歡迎大家分享自己的經(jīng)驗或秘技。
一個在線系統(tǒng)的性能不佳,主要原因都是來自于數(shù)據(jù)庫規(guī)劃及 SQL 語句層面,至于 .NET 程序撰寫不良都還在其次。 先將數(shù)據(jù)庫適度地做正規(guī)化,如:一個 Table 中,避免把常用的字段、很少用的字段,都塞在同一個表中,而影響數(shù)據(jù)掃描的速度。
---------------------------------------------- (2) 改寫 SQL 語句,注意 index 是否在查詢時有真的被用到 * 同樣的功能,一個不良的「關(guān)聯(lián)子查詢」和良好的「獨立子查詢」,之間的 SQL 性能差距,是不到一秒鐘和好幾分鐘以上的差距。 子查詢有分「關(guān)聯(lián)子查詢 (correlated subquery)」、「獨立子查詢」,前者應(yīng)盡可能少用。 Code
當(dāng)兩個表的記錄筆數(shù)越多時,在較極端的情況下,性能的差距,就會是不到一秒鐘,和十幾分鐘的差別。
---------------------------------------------- (3) 使用 Native 的 DataProvider 放棄 OleDb,改用 ADO.NET Native 的 DataProvider,如: SqlClient、OracleClient。但若您公司堅持要用 Sybase 這種從 2003 年之后,就不曾更新 DB driver 的數(shù)據(jù)庫,就只好繼續(xù)用性能不佳的 OleDb 去聯(lián)機了。 據(jù)版工我用 Visual Studio 內(nèi)建的 stress test 工具,測試 OleDb 和 SqlClient 的性能差距,模擬 30 人同時上線,用瀏覽器擷取一萬筆數(shù)據(jù),兩者的速度就差了一秒鐘;且當(dāng)數(shù)據(jù)庫的數(shù)據(jù)越多,或越多人同時上線時,性能差距會更明顯。 ---------------------------------------------- (4) 用程序或軟件做緩存 用程序做緩存,如 ASP.NET 從 1.x 時代,就已內(nèi)建的 Cache (緩存) 機制;或用一些第三方的輔助軟件、Framework,這方面若有其它網(wǎng)友知道好用的軟件,亦懇請留言告知。 ---------------------------------------------- (5) 用硬件做快取或緩沖、砸錢加裝 AP Server ITHome - 游戲基地網(wǎng)頁效能提升的關(guān)鍵人物 (此連結(jié)連至臺灣網(wǎng)頁,若無法開啟敬請見諒) : 以下引用自原文: 種種缺失使得網(wǎng)站的使用人數(shù)銳減。面對網(wǎng)站一堆問題,陳xx也決定要將網(wǎng)站再次大幅度調(diào)整,將之前的網(wǎng)頁程序,以及 SQL 查詢語句全部重寫,他們花了三個月的時間執(zhí)行。 陳xx還在原本的網(wǎng)頁服務(wù)器,與數(shù)據(jù)庫服務(wù)器的架構(gòu)中,加入一組應(yīng)用程序服務(wù)器,作為網(wǎng)頁服務(wù)器 cache 數(shù)據(jù)的來源。 改版之后的新網(wǎng)站,搜尋速度提升許多,先前每日的統(tǒng)計數(shù)據(jù)中,處理速度超過 3 秒的數(shù)據(jù)超過 50 萬筆;而改版后,每星期超過 3 秒的查詢不到 10 筆,而這少數(shù)反應(yīng)速度不夠快的查詢,也多是內(nèi)部作業(yè)執(zhí)行大量批處理導(dǎo)致的。 由于原本使用的 L4 Switch 較為老舊,負載量比較差,因此陳xx選擇將它汰換新的設(shè)備,加強負載量;恰好那時正好準(zhǔn)備將應(yīng)用服務(wù)器的架構(gòu)上線,就藉此機會將網(wǎng)絡(luò)架構(gòu)更新。陳xx說,這樣的架構(gòu)搭配負載較強的 L4 交換器,強化網(wǎng)站的處理性能,并憑借此抵御網(wǎng)絡(luò)攻擊。在此之后,網(wǎng)站依然會受到零星攻擊,但都不會對造成太大影響。 ---------------------------------------------- (6) 用硬件做快取或緩沖、砸錢加裝 AP Server 數(shù)字之墻 - 網(wǎng)站外銷的個人實踐(二)運營 (此連結(jié)連至臺灣網(wǎng)頁,若無法開啟敬請見諒) : 以下引用自原文: 全盛時期,來自美國 blog 的流量每天達 80 萬次。這個數(shù)字其實不高,對程序高手來說是小菜一碟,但筆者是半吊子工程師,知識有限也因此可能程序?qū)懙貌缓茫l頻被主機供貨商發(fā)信警告,要求改善網(wǎng)站系統(tǒng)性能。最后,我決定開發(fā) cache system。 cache system 緩存系統(tǒng)上線后,將數(shù)據(jù)庫讀寫,從每天 80 萬次降低到每天 16 萬次。這期間也請高手朋友幫忙進行數(shù)據(jù)庫結(jié)構(gòu)優(yōu)化,幫助很大。筆者在過程中學(xué)習(xí)到,一個良好的「緩存系統(tǒng) (cache system)」對于提供 Widget 功能的網(wǎng)站來說非常重要。 …中間略… 能夠做到隨時搬遷整個網(wǎng)站到另一家主機供貨商,除了程序本身的調(diào)整外,還要歸功于網(wǎng)站管理軟件的盛行。在此要推薦的一套稱為 Plesk 的網(wǎng)站管理軟件。有的主機供貨商會直接幫你安裝 Plesk ,免費或另外付費。 Plesk 的所有管理功能都是透過 Web 界面,方便到無以復(fù)加,大大降低對技術(shù)能力的要求。 除了 Plesk 以外,網(wǎng)站管理軟件還有其它選擇。還有 WHM 加上 cPanel 的組合,也是常見的網(wǎng)站管理解決方案。不過筆者還是比較偏好使用 Plesk,畢竟使用起來容易,也難怪他們的市場占有率一直是獨大。只是,功力高的工程師可能會喜歡 WHM + cPanel,因為彈性比較大。不論選擇哪一種,都可以幫助你節(jié)省許多時間。 ---------------------------------------------- (7) 加裝實體機器做 Loading Balance (負載平衡)。一些 Server OS 亦內(nèi)建此類設(shè)定功能。 ---------------------------------------------- (8) 程序技巧 - ADO.NET 能用 DataReader 就不要用 DataSet / DataTable,前者讀取速度快又不耗內(nèi)存;后者雖較有彈性,但速度較慢又會每個使用者消耗許多內(nèi)存。若您連 DropDownList 控件的數(shù)據(jù)來源,都用 SqlDataSource 控件的默認值 - DataSet,則當(dāng)頁面里塞了一堆下拉選單時,性能當(dāng)然會受影響。 但前提是程序員對 ADO.NET 要有一定程度的了解,若只會用 Visual Studio 透過圖形界面,拖拉 TableAdapter、DataTable、.xsd 就免談了。 若為 DataTable 建立 Primary Key,DataTable 會建立一個索引,追蹤新增到 DataTable 中的數(shù)據(jù)是否符合此條件約束 (constraint)。ADO.NET 2.0 會使用 algorithm 的「紅黑樹算法 (Red-Black Tree,是一種「平衡樹」算法) 去處理索引,讓 DataTable 的數(shù)據(jù)量大時,較方便維護索引;但缺點是建立索引時會降低一些性能。
Programming Microsoft ADO.NET 2.0 Core Reference: 有探討許多市面上書籍少見的深入內(nèi)容,像 Oracle + ADO.NET 的各種應(yīng)用、Connection Pooling 的特性、各種的數(shù)據(jù)庫 Balk (批次) 作業(yè)應(yīng)用。
適時調(diào)整 SqlDataSource 控件的 DataSourceMode 屬性: 使用 ADO.NET 的 NextResult 方法取得多個 Result Set: ---------------------------------------------- (9) 程序技巧 - .NET 語法 * 避免一些書上教的,把 DataTable 或大量數(shù)據(jù),直接塞進 Session 里,此舉在真正要上線的系統(tǒng)必死無疑。Session 在多人同時上線時,內(nèi)存的消耗是很可觀的,因為 Session 是每個用戶各存一份在服務(wù)器的內(nèi)存里,而非像「緩存 (cache)」是所有的用戶共享服務(wù)器的一塊內(nèi)存。在很多 ASP.NET 的需求中,可用 HiddenField 控件或 ViewState 取代 Session。 * 能用「泛型 (Generics)」就不要用舊版的寫法,Generics 除了安全外,亦可避免 .NET 類型在 Boxing / Unboxing 轉(zhuǎn)型時影響性能,例如: 當(dāng)然上述前提,是系統(tǒng)要用 .NET 開發(fā),還在靠 ASP 或非 OOP 語言硬撐的舊系統(tǒng)就免談了。
Hashtable 和 Dictionary 集合類型: ---------------------------------------------- (10) 程序技巧 - 數(shù)據(jù)庫「事務(wù) (Transaction)」 您是否知道 SQL Server 的默認「事務(wù)隔離等級 (Isolation Level)」,是「ReadCommitted」,當(dāng)您在寫 ADO.NET 用了 SqlTransaction 時,默認是當(dāng)某個人在修改某一筆記錄時,其它所有讀取這一筆記錄的人,都會被「鎖定 (lock)」住,造成其它全部用戶的瀏覽器都在等待中,無法做其它工作。 而 Oracle 事務(wù)的特性,是絕不會有類似無法讀取的情形,至少會用類似 SQL Server 2005 新增的「快照隔離 (Snapshot Isolation)」,讓用戶至少能先讀取到未 Commit 或 Rollback 的記錄,而不用呆坐在瀏覽器前面傻等。 不過 SQL Server 2005 的「快照隔離」默認未啟用。用 SQL Server 開發(fā)的系統(tǒng),若怕用戶被鎖定的問題,可視 project 需求,改用最寬松的「ReadUncommitted」事務(wù)隔離等級,其特性為不會造成任何鎖定,但可能會造成 Dirty Read。SQL Server 有下列七種「事務(wù)隔離等級」,有興趣的網(wǎng)友可去查詢 ADO.NET 書籍或 MSDN Library: Chaos
Oracle 11g 學(xué)習(xí)筆記 (5): ---------------------------------------------- (11) ASP.NET 分頁 GridView + SqlDataSource 的默認行為,就是每次換頁或排序時,不管數(shù)據(jù)庫有幾筆記錄都全部重撈一次;當(dāng)數(shù)據(jù)庫有一百萬筆數(shù)據(jù),就在每個用戶換頁時,都一百萬筆全部重撈出來,此舉消耗了大量的 Web server/ AP server 內(nèi)存、數(shù)據(jù)庫系統(tǒng)資源、網(wǎng)絡(luò)頻寬,結(jié)果網(wǎng)站性能可想而知。 很多企業(yè)內(nèi)的小型網(wǎng)站,為了省錢,隨便外包給低價搶標(biāo)的工作室,或沒經(jīng)驗的學(xué)生和 SOHO 族,可能因此埋下了恐怖的后遺癥。最可怕的是這些未爆彈,在開發(fā)期間和系統(tǒng)剛上線、數(shù)據(jù)量還很少時,都感覺不出來,有如癌癥一樣,會在將來忽然爆發(fā)。
ASP.NET 數(shù)據(jù)分頁 1 ~ 4 篇 series : ---------------------------------------------- (12) ASP.NET AJAX 的 UpdatePanel 控件不是萬能的 以下引用自 MSDN Magazine: 不論好壞,UpdatePanel 控件都是 ASP.NET AJAX 社區(qū)所喜愛的。我說“好”,是因為 UpdatePanel 使部分頁面呈現(xiàn)變得相當(dāng)簡單,而說“壞”,是因為它的簡便和易用性是以效率和令人啼笑皆非的帶寬為代價的。 UpdatePanel 可以為一般的網(wǎng)頁帶來 AJAX 神奇的好處,但是它不能提供我們與 AJAX 正常關(guān)聯(lián)的高效性。例如,您是否知道,當(dāng) UpdatePanel 控件對服務(wù)器執(zhí)行異步 AJAX 回調(diào)以更新其內(nèi)容時,這個請求包含了常規(guī) ASP.NET 回發(fā)所包含的一切,其中還包括 ViewState 呢?具有太多 ViewState 的頁面會降低性能,并且具有太多 ViewState 的頁面在 ASP.NET 應(yīng)用程序中都太常見。 如果您準(zhǔn)備使用 UpdatePanel 控件,您需要清楚您在準(zhǔn)備干什么。在許多情況下,從性能的角度而言,應(yīng)用程序最好是不使用 UpdatePanel,而是使用對 WebMethods 或頁面方法的異步調(diào)用。 …中間略… 當(dāng)您使用 UpdatePanel 在一個頁面上執(zhí)行無閃爍更新時,您可能會認為您在進行高效構(gòu)建。畢竟,UpdatePanel 使用的是 AJAX,不是嗎?不幸的是,如果您在 UpdatePanel 更新時檢驗一下網(wǎng)絡(luò)中的通信,您會發(fā)現(xiàn)您根本就沒有保存什么東西,至少是在發(fā)送的時候沒有保存。通常在回發(fā)期間傳送到服務(wù)器的 ViewState 數(shù)據(jù)(與其他數(shù)據(jù))也會在 UpdatePanel 回調(diào)期間傳送。事實上,來自 UpdatePanel 的異步 XML-HTTP 請求中所增長的數(shù)據(jù),幾乎與在標(biāo)準(zhǔn) ASP .NET 回發(fā)中增長的數(shù)據(jù)相同。下面是有關(guān) ASP.NET AJAX 不可告人的秘密:UpdatePanel 雖易于使用,但是通信效率不高。 幾乎沒有什么辦法可讓您提高 UpdatePanel 的效率,但是您可以放棄使用 UpdatePanel,并轉(zhuǎn)而使用 ASP.NET AJAX 的其他功能來更新頁面內(nèi)容,它不僅同樣流暢,而且更加高效。它只需要多一點點力氣,但是最后的結(jié)果往往讓人覺得是值得付出的,因為您可以大大降低在客戶端與服務(wù)器之間傳輸?shù)臄?shù)據(jù)量。
UpdatePanel 提示和技巧 (MSDN Magazine, 2007/6): ---------------------------------------------- (13) Design Patterns 雖然「設(shè)計模式」不是為解決性能問題而誕生的,但可適度防止沒經(jīng)驗的新人做出蠢事。多學(xué)一些 .NET 技術(shù)敵營注重的系統(tǒng)架構(gòu)、OOAD、Design Patterns 和相關(guān)的 Framework,對提升自己的身價和薪資也有幫助。
C# 3.0 Design Patterns: Head First Design Patterns: ----------------------------------------------
本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/xiaokuang513204/archive/2009/10/29/4743341.aspx |
|