你的老板或客戶
是否曾和你抱怨公司的網站性能愈來愈差?網站大家都會寫
自從有了 Visual Studio 之後
連你家樓下的正妹小喵和隔壁的王大嬸都會寫 ASP
NET
但同樣的一個畫面
背後的性能卻可能是天差地遠
更惶論多人同時上線的企業網站
而程序員的身價也因此有所差別
本帖提供一些改善網站性能的點子
從硬件
軟件
程序技巧的層面都有
也歡迎大家分享自己的經驗或秘技
(
) 重新調整或重新設計 DB schema
索引 (index)
一個在線系統的性能不佳
主要原因都是來自於數據庫規劃及 SQL 語句層面
至於
NET 程序撰寫不良都還在其次
先將數據庫適度地做正規化
如
一個 Table 中
避免把常用的字段
很少用的字段
都塞在同一個表中
而影響數據掃描的速度
應該將很少用的字段
另切割出來成為另一個表
(
) 改寫 SQL 語句
注意 index 是否在查詢時有真的被用到
* 同樣的功能
一個不良的「關聯子查詢」和良好的「獨立子查詢」
之間的 SQL 性能差距
是不到一秒鐘和好幾分鐘以上的差距
* 一些 SQL 關鍵詞
只要一出現在 SQL 語句中
就可能造成表的「索引 (index)」完全失效或部分失效
變成要整個表去逐行逐列地掃描
例如: NOT
NOT IN
!=
<>
OR
等關鍵詞
還有「LIKE
%關鍵詞
」的模糊查詢
也會造成索引失效
但「LIKE
關鍵詞%
」就不會造成索引失效
(
) 使用 Native 的 DataProvider
放棄 OleDb
改用 ADO
NET Native 的 DataProvider
如: SqlClient
OracleClient
但若您公司堅持要用 Sybase 這種從
年之後
就不曾更新 DB driver 的數據庫
就只好繼續用性能不佳的 OleDb 去聯機了
據版工我用 Visual Studio 內建的 stress test 工具
測試 OleDb 和 SqlClient 的性能差距
模擬
人同時上線
用浏覽器撷取一萬筆數據
兩者的速度就差了一秒鐘
且當數據庫的數據越多
或越多人同時上線時
性能差距會更明顯
(
) 用程序或軟件做緩存
用程序做緩存
如 ASP
NET 從
x 時代
就已內建的 Cache (緩存) 機制
或用一些第三方的輔助軟件
Framework
這方面若有其它網友知道好用的軟件
亦懇請留言告知
(
) 用硬件做快取或緩沖
砸錢加裝 AP Server
ITHome
游戲基地網頁效能提升的關鍵人物
以下引用自原文:
種種缺失使得網站的使用人數銳減
面對網站一堆問題
陳xx也決定要將網站再次大幅度調整
將之前的網頁程序
以及 SQL 查詢語句全部重寫
他們花了三個月的時間執行
陳xx還在原本的網頁服務器
與數據庫服務器的架構中
加入一組應用程序服務器
作為網頁服務器 cache 數據的來源
改版之後的新網站
搜尋速度提升許多
先前每日的統計數據中
處理速度超過
秒的數據超過
萬筆
而改版後
每星期超過
秒的查詢不到
筆
而這少數反應速度不夠快的查詢
也多是內部作業執行大量批處理導致的
由於原本使用的 L
Switch 較為老舊
負載量比較差
因此陳xx選擇將它汰換新的設備
加強負載量
恰好那時正好准備將應用服務器的架構上線
就藉此機會將網絡架構更新
陳xx說
這樣的架構搭配負載較強的 L
交換器
強化網站的處理性能
並憑借此抵御網絡攻擊
在此之後
網站依然會受到零星攻擊
但都不會對造成太大影響
(
) 用硬件做快取或緩沖
砸錢加裝 AP Server
數字之牆
網站外銷的個人實踐
(二)運營
以下引用自原文:
全盛時期
來自美國 blog 的流量每天達
萬次
這個數字其實不高
對程序高手來說是小菜一碟
但筆者是半吊子工程師
知識有限也因此可能程序寫得不好
頻頻被主機供貨商發信警告
要求改善網站系統性能
最後
我決定開發 cache system
cache system 緩存系統上線後
將數據庫讀寫
從每天
萬次降低到每天
萬次
這期間也請高手朋友幫忙進行數據庫結構優化
幫助很大
筆者在過程中學習到
一個良好的「緩存系統 (cache system)」對於提供 Widget 功能的網站來說非常重要
…中間略…
能夠做到隨時搬遷整個網站到另一家主機供貨商
除了程序本身的調整外
還要歸功於網站管理軟件的盛行
在此要推薦的一套稱為 Plesk 的網站管理軟件
有的主機供貨商會直接幫你安裝 Plesk
免費或另外付費
Plesk 的所有管理功能都是透過 Web 界面
方便到無以復加
大大降低對技術能力的要求
除了 Plesk 以外
網站管理軟件還有其它選擇
還有 WHM 加上 cPanel 的組合
也是常見的網站管理解決方案
不過筆者還是比較偏好使用 Plesk
畢竟使用起來容易
也難怪他們的市場占有率一直是獨大
只是
功力高的工程師可能會喜歡 WHM + cPanel
因為彈性比較大
不論選擇哪一種
都可以幫助你節省許多時間
(
) 加裝實體機器做 Loading Balance (負載平衡)
一些 Server OS 亦內建此類設定功能
(
) 程序技巧
ADO
NET
能用 DataReader 就不要用 DataSet / DataTable
前者讀取速度快又不耗內存
後者雖較有彈性
但速度較慢又會每個使用者消耗許多內存
若您連 DropDownList 控件的數據來源
都用 SqlDataSource 控件的默認值
DataSet
則當頁面裡塞了一堆下拉選單時
性能當然會受影響
但前提是程序員對 ADO
NET 要有一定程度的了解
若只會用 Visual Studio 透過圖形界面
拖拉 TableAdapter
DataTable
xsd 就免談了
若為 DataTable 建立 Primary Key
DataTable 會建立一個索引
追蹤新增到 DataTable 中的數據是否符合此條件約束 (constraint)
ADO
NET
會使用 algorithm 的「紅黑樹算法 (Red
Black Tree
是一種「平衡樹」算法) 去處理索引
讓 DataTable 的數據量大時
較方便維護索引
但缺點是建立索引時會降低一些性能
此外
數據庫的訪問和撈值
應該盡量在一次 DB connection 做完
一個 connection 可搭配多個 DbCommand 對象使用
不用每次都一個 DbConnection 配一個 DbCommand
在此推薦一本不錯的 ADO
NET 原文書:
Programming Microsoft ADO
NET
Core Reference:
Microsoft%C
%AE
ADO
NET
Core
Reference/dp/
X/ref=sr_
_
?ie=UTF
&s=books&qid=
&sr=
有探討許多市面上書籍少見的深入內容
像 Oracle + ADO
NET 的各種應用
Connection Pooling 的特性
各種的數據庫 Balk (批次) 作業應用
(
) 程序技巧
NET 語法
* 避免一些書上教的
把 DataTable 或大量數據
直接塞進 Session 裡
此舉在真正要上線的系統必死無疑
Session 在多人同時上線時
內存的消耗是很可觀的
因為 Session 是每個用戶各存一份在服務器的內存裡
而非像「緩存 (cache)」是所有的用戶共享服務器的一塊內存
在很多 ASP
NET 的需求中
可用 HiddenField 控件或 ViewState 取代 Session
* 能用「泛型 (Generics)」就不要用舊版的寫法
Generics 除了安全外
亦可避免
NET 類型在 Boxing / Unboxing 轉型時影響性能
例如:
能用 List<string> 就不要用舊的 ArrayList
能用 Dictionary<TKey
TValue> 就不要用 Hashtable 或跑雙層的循環 (loop)
因 ArrayList
Hashtable 的 element 屬於 object 類
在存儲或檢索如 int 等「值類型 (Value Type)」時
會引發 Boxing / Unboxing
在大多數的情況下
List
Dictionary 等泛型類
擁有較佳的效率
而且是類型安全的
當然上述前提
是系統要用
NET 開發
還在靠 ASP 或非 OOP 語言硬撐的舊系統就免談了
(
) 程序技巧
數據庫「事務 (Transaction)」
您是否知道 SQL Server 的默認「事務隔離等級 (Isolation Level)」
是「ReadCommitted」
當您在寫 ADO
NET 用了 SqlTransaction 時
默認是當某個人在修改某一筆記錄時
其它所有讀取這一筆記錄的人
都會被「鎖定 (lock)」住
造成其它全部用戶的浏覽器都在等待中
無法做其它工作
而 Oracle 事務的特性
是絕不會有類似無法讀取的情形
至少會用類似 SQL Server
新增的「快照隔離 (Snapshot Isolation)」
讓用戶至少能先讀取到未 Commit 或 Rollback 的記錄
而不用呆坐在浏覽器前面傻等
不過 SQL Server
的「快照隔離」默認未啟用
用 SQL Server 開發的系統
若怕用戶被鎖定的問題
可視 project 需求
改用最寬松的「ReadUncommitted」事務隔離等級
其特性為不會造成任何鎖定
但可能會造成 Dirty Read
SQL Server 有下列七種「事務隔離等級」
有興趣的網友可去查詢 ADO
NET 書籍或 MSDN Library:
Chaos
ReadCommitted // SQL Server 默認值
ReadUncommitted // 最寬松
會有 Dirty Read
RepeatableRead
Serializable // 最嚴
會有大量的鎖定
Snapshot
Unspecified
(
) ASP
NET 分頁
GridView + SqlDataSource 的默認行為
就是每次換頁或排序時
不管數據庫有幾筆記錄都全部重撈一次
當數據庫有一百萬筆數據
就在每個用戶換頁時
都一百萬筆全部重撈出來
此舉消耗了大量的 Web server/ AP server 內存
數據庫系統資源
網絡頻寬
結果網站性能可想而知
很多企業內的小型網站
為了省錢
隨便外包給低價搶標的工作室
或沒經驗的學生和 SOHO 族
可能因此埋下了恐怖的後遺症
最可怕的是這些未爆彈
在開發期間和系統剛上線
數據量還很少時
都感覺不出來
有如癌症一樣
會在將來忽然爆發
(
) ASP
NET AJAX 的 UpdatePanel 控件不是萬能的
以下引用自 MSDN Magazine:
不論好壞
UpdatePanel 控件都是 ASP
NET AJAX 社區所喜愛的
我說
好
是因為 UpdatePanel 使部分頁面呈現變得相當簡單
而說
壞
是因為它的簡便和易用性是以效率和令人啼笑皆非的帶寬為代價的
UpdatePanel 可以為一般的網頁帶來 AJAX 神奇的好處
但是它不能提供我們與 AJAX 正常關聯的高效性
例如
您是否知道
當 UpdatePanel 控件對服務器執行異步 AJAX 回調以更新其內容時
這個請求包含了常規 ASP
NET 回發所包含的一切
其中還包括 ViewState 呢?具有太多 ViewState 的頁面會降低性能
並且具有太多 ViewState 的頁面在 ASP
NET 應用程序中都太常見
如果您准備使用 UpdatePanel 控件
您需要清楚您在准備干什麼
在許多情況下
從性能的角度而言
應用程序最好是不使用 UpdatePanel
而是使用對 WebMethods 或頁面方法的異步調用
…中間略…
當您使用 UpdatePanel 在一個頁面上執行無閃爍更新時
您可能會認為您在進行高效構建
畢竟
UpdatePanel 使用的是 AJAX
不是嗎?不幸的是
如果您在 UpdatePanel 更新時檢驗一下網絡中的通信
您會發現您根本就沒有保存什麼東西
至少是在發送的時候沒有保存
通常在回發期間傳送到服務器的 ViewState 數據(與其他數據)也會在 UpdatePanel 回調期間傳送
事實上
來自 UpdatePanel 的異步 XML
HTTP 請求中所增長的數據
幾乎與在標准 ASP
NET 回發中增長的數據相同
下面是有關 ASP
NET AJAX 不可告人的秘密
UpdatePanel 雖易於使用
但是通信效率不高
幾乎沒有什麼辦法可讓您提高 UpdatePanel 的效率
但是您可以放棄使用 UpdatePanel
並轉而使用 ASP
NET AJAX 的其他功能來更新頁面內容
它不僅同樣流暢
而且更加高效
它只需要多一點點力氣
但是最後的結果往往讓人覺得是值得付出的
因為您可以大大降低在客戶端與服務器之間傳輸的數據量
(
) Design Patterns
雖然「設計模式」不是為解決性能問題而誕生的
但可適度防止沒經驗的新人做出蠢事
多學一些
NET 技術敵營注重的系統架構
OOAD
Design Patterns 和相關的 Framework
對提升自己的身價和薪資也有幫助
From:http://tw.wingwit.com/Article/program/net/201311/12137.html