網站的視覺設計及內容,是能否吸引訪客的重要因素之一,但也不能因而顧此失彼,造成網站效能的瓶頸。從過去的訪客行為研究 分析指出,等待一個網頁的呈現時間不能超過9秒鐘,但面對目前網頁內容多媒體化的現實挑戰,要達到這樣的目標,在前端頁面的設計上,也就需要多花些心思。

著重網頁前端的效能改善

《High Performance Web Sites》內容主要針對網站前端的設計人員所設計。作者曾經擔任雅虎CPO(Chief Performance Officer),在雅虎負責研究改善網站效能的方法,他以多年的經驗整理出14個網站前端設計需要注意的準則。全書內容簡明扼要,具有網站設計經驗的讀者,可以快速領略要點;初次接觸的生手,也可以透過本書建立良好的網站設計觀念。

14條必勝定律

如何有效提升網站效能?作者針對網站效能最佳化歸納出以下方針,並舉例加以說明:

1. 減少需要發出HTTP Request的數量

當你設計的網頁中包含的元件數量越多,Client需要對網站伺服器發出的HTTP Request也會增加,同時也會延長網頁處理的時間。

2. 採用Content Delivery Network服務

由Mirror Image、Akamai、SAVVIS等業者所提供的Content Delivery Network(CDN,內容遞送網路服務),可以供應強大的全球網路基礎架構,將網站以最有效的方式傳送給全球使用者,並自動幫網站選擇最佳路徑傳送資 料,例如,根據瀏覽者所在地、網路品質及流量狀況,選擇距離用戶端最近的資料中心傳送資料,確保網頁的瀏覽品質及運作速度。

3. 在網頁中加入過期檔頭

你可以利用這個設定讓網頁具備快取機制,縮短頁面載入時間,尤其是針對內容不常變動的網頁。當然這樣的運用,得視你的網頁性質而定,若內容變動頻率高的網頁,則不適用此方式。

4. 善用Gzip壓縮機制

以XML/HTTP做為資料交換的開放格式已經十分普遍,傳輸的檔案體積,較過去單純的 EDI方式增加許多,用傳送壓縮時間換取傳輸時間,也是一種提升效率的策略,目前常見的網站伺服器大都支援此項技術。你甚至也可以視情況選擇壓縮 HTML、CSS及JavaScript的檔案內容。

5. 將Stylesheet置於網頁頁首

將樣式表(Stylesheet)置於頁首,可以讓CSS設定先行載入,在第一時間套用設定直接呈現網頁。相較於把樣式表放置在頁尾,等所有內容都下載完畢後才套用,樣式表置於頁首的作法,除了頁面呈現速度較快,載入過程中也較不易造成空白頁的出現。

6. 將Script內容置於頁尾

許多實際狀況中,網頁包含的Script程式,本身並不需要在載入後立即執行,所以作者建議將這些程式碼置於頁尾,至少內容可以在傳輸前段時間即備妥,讓使用者有較佳的瀏覽體驗。

7. 避免CSS Expression的撰寫方式

CSS Expression的目的,在於讓自訂樣式的語法可以取代部分的Script內容,雖然這麼做很好用,但因網頁顯示過程中花費較多的邏輯判斷時間,造成網站效能的致命傷。

8. 將JavaScript及CSS內容獨立於網頁內容之外

透過獨立內容的方式,讓HTML本文檔案縮小,而且可以同時被瀏覽器下載,以縮短網頁呈現的時間。

9. 減少DNS查找的次數,縮短取得網頁內容之前的前置時間

雖然網頁可以串連不同網站來源的內容,但是不同網站來源的內容一旦太多,便會延遲頁面載入速度;如果能夠減少網頁內不同網站來源的內容,就可以減少從用戶端發出的DNS Request數量,縮短DNS的查詢時間。

10. JavaScript內容精簡化

網頁中的JavaScript也是下載的一部分,所以當程式碼內容較多時,亦會直接影響網頁下載的速度。檢視一下程式碼,移除不必要的部分。

11. 避免重導向

網頁重新導向是很方便的功能,但對於使用者而言,他必須等待更多的時間直到最終頁面被載入,所以應該盡可能避免使用重導向轉址功能。

12. 移除重複的Script程式碼

重複的Script程式碼需要花費更多的下載時間,這個問題通常發生在程式碼未能妥善模組化的情況下,檢查一下你的Script程式吧。

13. 善用Etag

透過設定Web Server中的Entity Tag方式,能決定網頁中被快取的內容,以加速網頁呈現,但也得視網頁內容特性而定,Etag主要運用在靜態頁面上,而動態顯示內容的網頁則不適用此方式。

14. 讓Ajax程式可做到暫存快

Ajax架構透過非同步的傳輸方式,讓使用者具有較佳的使用體驗,卻不見得是效能的保證。除了可以透過利用Gzip壓縮、避免DNS查找次數、簡化JavaScript內容之外,控制HTTP過期檔頭來快取Ajax網頁,也能發揮明顯效果。

拿知名網站開刀,保證你大呼過癮

本書最後以全球十大網站做為案例分析的對象,包括Yahoo、Google、Amazon、YouTube等。這些網站之所以成功,除了透過內容及社群機制吸引訪客,在網站效能的表現上,也必須克服流量提高所帶來的問題。

作者使用3個度量值(Page Weight、Response Time、YSlow Grade)逐一檢視這些網站,找出問題點以及可以改善的地方,配合前述建議的14項準則,解決效能表現不佳的現象。

作者表示,這些準則都經過實務證明為有效的解法,可以幫網站減少平均二至三成的網路傳輸時間。對照本書,檢視你的網站架構出了哪些問題,並對症下藥加以落實,我相信可以讓訪客感受到明顯的效能提升。

又是一個可能會得罪其他單位的任務,在最近一次的專案中,為了改善現有系統效能不佳的問題,開始從不同Tier分別查起,最後發現應用程式對資料庫表格的查詢語法不當,導致資料處理的時間過久,結果造成網頁回應速度過慢。唉,又是SQL指令惹的禍!

其實程式設計師在不眠不休狂趕專案進度的狀況下,首要前提是功能上的需求能先被滿足,行有餘力才會考慮到效能問題。軟體專案經理既要固守優質軟體的理想,卻發覺實現的門檻愈來愈高,這樣的程式品質在系統上線初期也許還不會被發覺,當資料量日益成長之後,問題便慢慢浮現。

都是自動化惹的禍?

與資料層面有關的效能議題,除了資料庫系統本身的調校外,對於應用程式對資料庫進行存取的SQL語法,其實也是關鍵之一。

對於系統方面的調校,通常會落在DBA身上,而SQL的撰寫則是程式開發人員所需要了解。現在為了符合快速開發及方便使用的精神,在SQL語法的撰寫上, 常會透過語法產生器的方式來產生SQL查詢指令,若是遇到較複雜的結構時(像是多個資料表進行Join、多層次的子查詢Subquery、WHERE條件 組合繁多時),由特定工具所自動產生出來的語法是否能符合效能的要求,就有待商榷了。

先前筆者曾經介紹《Learning SQL》(可參見iThome電腦報第224期),該書屬於學習SQL的入門書,從最基本的觀念開始闡述。而這次針對SQL指令的優化,筆者找了兩本建議 閱讀的書籍:《SQL Tuning》及《SQL Performance Tuning》,兩本都是針對SQL指令效能調校議題深入討論的書籍,而且不限定於某一個廠牌的資料庫產品上,建議具備基本SQL使用經驗及資料庫系統概 念的讀者閱讀。

SQL調校不只是指令的善用,亦是查詢結構的改良

在O’reilly出版的《SQL Tuning》書中,你可以學習如何掌控你所撰寫的SQL指令的執行方式及背後的處理流程,利用作者所提出的查詢流程圖(Query Diagramming)獨特方法,將SQL的查詢語法以結構化流程圖的方式,抽絲剖繭呈現,幫助你在思考類似問題時,能加速找出癥結所在。

在本書的第二章中,便從資料庫系統的架構談起,探討了資料庫對於SQL查詢在執行時的內部作業流程,像是如何有效運用快取記憶體(Cache)來 加速執行效率、資料表在實體檔案系統中的儲存方式、資料讀取時其資料表的實際走訪方式、各式索引的結構及其產生的成本為何、以及在執行Join運算時的處 理過程。這裡提供了一些建議的設計原則,讓你可以將基礎概念搞清楚,才能充分掌握SQL內部運作的原理。

在SQL效能分析時,執行計畫(Execution Plan)常常被用來檢測SQL語法的適當性,成為找問題的工具。第三、四章教你如何使用、解讀、進而有效控制執行計畫,協助自己對SQL語法的改良。

另外,作者除了提出概括性的通則之外,針對目前市面上通行的三大品牌資料庫產品(Oracle、IBM DB2、MSSQL)也有分節介紹,可依你的需求選讀。

Query Diagramming為本書的核心思想

除了執行計畫進行效能分析,第五至七章所提到的查詢圖示法(Query Diagramming Method)便是本書作者所提出的核心思想。此分析技術透過一連串的點與線的組合,將SQL查詢語法拆解成圖,並標上在查詢語法中相關資料表的參考權重 數字,發掘可能發生的效能瓶頸所在。這樣的觀念類似演算法裡的Big O Notation,用來釐清程式邏輯的複雜度所造成的成本,找出執行最費時的地方。

這樣的方法論可依圖示內含資訊的完整度而分為:完整圖示法(Full Diagrams)以及簡易圖示法(Simplified Diagrams)。作者在本書中利用案例來逐步分解,將SQL指令轉化成4種不同的符號來表示:

● 節點(Node):用來表示資料庫中的資料表(Table),也就是SQL指令中在FROM子句的資料表。

● 連結(Link):代表資料表之間的關連性,以帶有箭頭的線條表示,方向意指關聯欄位之間的唯一性(Unique)。

● 有底線的數字:標註於節點旁,表示符合WHERE條件的記錄占該資料表的比例,以小於1的小數來表示。

● 無底線的數字:標註在連結的兩端,分別表示作者所定義的Master Join Ratio及Detail Join Ratio(詳細定義內容請參考本書)。

當然,還有一些你認為也會影響執行效能的變數(像是被SELECT的欄位內容、ORDER BY排序方式等)並沒有被納入,作者在本章也有詳細說明此分析工具設計的原因。

結合範例說明分析方法

基於這樣的分析工具,作者在第七章以實例演練說明更複雜的查詢語法,讓讀者更清楚如何落實這樣的分析工具。作者倡導此分析工具亦有他的理由,在第八章更以專章說明為何這樣的分析方式是有效的。

作者嘗試以標準的分析方法來處理所有的查詢問題,但遇到某些特例時,需要再延伸出不同的應用方式來處理。

第九章舉出一些特例狀況,並說明如何運用Query Diagramming的方式來進行分析,像是查詢成本甚高的OUTTER JOIN等。遇到連調校後也無法滿足的狀況時,作者則建議以其他方式(非單純調整SQL語法、回傳資料量過大時可以批次方式產出靜態結果,或是以強制性的 查詢條件,以及透過中介層軟體來配合加快執行速度等方式來改善)來補其不足。

值得一提的是,作者將從發現問題到尋得解法的整個處理流程,在附錄中以實例的方式從頭到尾完整地說明分析及處理的過程,有助於讀者熟悉理論如何落實到實際作法。

SQL最佳化的指令工具書

而Addison Wesley所出版的《SQL Performance Tuning》一書則是偏向SQL指令的撰寫原則討論,每個與查詢有關的關鍵字都被作者詳盡說明,全書花了不少篇幅討論如何寫出較好的SQL指令,你可以 逐章閱讀,或當成工具書,在實際寫作時查閱參考。本書內容的特點如下:

● 作者針對相同結果提供不同寫法的SQL指令,你可以比較個中差異,有助於了解每個指令的特性以及適合使用時機。

● 由於本書內容不綁定任何特定資料庫產品,因此,在每個指令的章節開始,作者都貼心地整理市面上知名資料庫系統對指令、運算式以及資料型態的支援狀況,避免讀者搞錯SQL的用法。

● 書中建議較佳的SQL指令撰寫方式,會在該指令下方加註GAIN: x/8的參考數據,表示該指令在本書所採用測試的8大DBMS產品中,在效能上表現相對較佳的比例。這樣的參考數字有助於了解一樣的寫法,在不同的 DBMS中是否仍表現優異,讓讀者了解該指令對DBMS實際的影響程度。

● 為求所撰寫的SQL指令能支援異質資料庫,本書倡導程式可攜性(Portability)的精神,利用ANSI-SQL落實到書中的每個範例中。

● 如果你想快速閱讀,每個章節後的結語(The Bottom Line)列出了該指令的使用建議及應該避免的用法,方便沒什麼時間仔細研讀的讀者使用。

雖然目前市面上所通行的資料庫系統產品,號稱已對SQL命令的執行進行最佳化的設計,意謂程式設計人員不需要花太多心思在SQL語法本身效能的改 善,這樣可能造成意想不到的結果。若開發人員也能建立正確的設計觀念,在設計階段就納入考量,未來可能引發的問題也就能被減少許多。

不同時機妥善運用,讓你如虎添翼

這次介紹的兩本書使用時機各有不同。《SQL Performance Tuning》在於讓程式開發人員奠定良好的SQL指令實作基礎,在系統實作初期即能引用較佳的撰寫方式進行開發,避開不良設計,在有限的測試資料數量及 資料本身下,先行達到某一水準;在壓力測試進行時餵入大量測試資料後,以《SQL Performance Tuning》中提到的分析工具,來檢視原本設計的SQL語法是否有效能上的疑慮,找出問題所在進而改善。

在不同的專案時機點搭配兩本書的閱讀,相信可以讓你對自己寫出來的SQL指令更具信心!總而言之,還是那句老話:「程度不只是要寫得出來,還要寫得好!」

Follow

Get every new post delivered to your Inbox.