什麼是性能調優呢?一般是當使用者抱怨“太慢了”、“性能不足”、“軟硬體需要更新了”等問題時,提供較佳的性能。但不是要解決使用者所說的“這系統毀了”、“它不會工作了”等問題,這可能需要的是備援復原、提高系統可獲得性(HA high Availability)等解決方案。但就資料庫系統而言,規劃高可獲得性的架構(如SQL Cluster、Mirroring、Log Shipping、Replication等)不會提升系統性能,還要注意是否降低了性能。
而一般觀測性能問題的現象有:
系統響應速度太慢。
每秒所完成的系統輸出/入低于預期。
相同的環境,但每秒鐘所完成的批操作較先前少。
系統資源(如CPU、記憶體、硬碟或網絡等)長時間處于耗盡的狀态。
通常調校的目标是以使用者的期望為依據,除非你的數學與資訊基本功非常紮實,否則很難知道調校的極限在哪。是以,我們的目标往往是符合使用者的期盼即可
建立性能的基線
調校性能的第一個工作應該是建立性能的基線(baseline),所需的類型有:
昔日系統正常運作時的資料。
調校前系統的各種資料。
使用者希望達到的目标。
基線是用來比較的,任何性能調校的動作都應該依憑資料,不要訴諸情緒。筆者常聽到工程師說“今天的性能感覺比較差了”或是“現在系統響應比較慢了”。這種話是我們要幫使用者解決問題的起因,但不應該是工程師講的話。人的感覺非常不準,可能是心情不好,可能是對工作不滿意,對系統的包容力就比較差,感覺就不好了。
系統響應比較慢,要知道正常是多少、慢了多少、時間差是多少、資料量多少、多少人同時上線、處理量多少等。也就是要有基線,有客觀的資料,這才有好的調校基礎。而通常筆者碰到的是:工程師與使用者們忙了一天,精疲力竭後,會安慰自己“性能比較好了”。
如前文所述,一般要将使用者的期待量化,例如,使用者可以接受系統的響應時間是3~5 秒。而使用者的期待通常是來自于以下方面。
工作需求:如一定要在某個時間點前完成,一秒之内要完成多少交易量才能滿足多人通路等。
以往系統的使用經驗。
一些性能資料值(benchmark):不管是廠家提供的,還是業界提出的标準值。
其他使用者使用類似功能的經驗。
為什麼讨論這個呢?因為期待要合理。不要第一次開車開奔馳,然後誤以為全世界的汽車開起來都要像這樣。或許你會覺得這不可能發生。但事實上,若以往的系統是以Windows Form為基礎,現在一模一樣的功能,但改為以Web Form為基礎,在相同的硬體上,可能響應就比較慢。畢竟以往從SQL Server或COM+/MTS直接傳資料給編譯過的VB 前端程式呈現結果,系統架構簡單有效率且互動功能豐富。而Web版的ASP/ASP. NET應用程式要先将SQL Server或COM+/MTS的結果資料轉換成HTML,再用效率也不高的HTTP通信協定傳回到前端,最後還要浏覽器遵從HTML 或DHTML 訓示符,目前繪制界面,整體系統的性能當然不如以往的程式架構。
若使用者端的機器本身很快,使用者或許還感受不到這個差異,然而筆者曾碰到的情況:使用古老的機器,但要求Web Form 長得和Win Form 一樣,并且功能還要更多,而能忍受的響應時間相同,這就難如登天了。
另外,性能調校代表着成本(cost)支出,成本可能是實質的錢,也可能是工程師的時間與精力,使用者的忍耐等待。在理想狀況下,是把系統中最貴的部分發揮到極限,能夠以最低的成本發揮系統最大的性能。若是自己開發的程式,這往往代表着硬體采購是系統開發中最貴的部分,是以,會采取重新設計系統的解決方式,如資料庫邏輯使用方式重新切割、查詢方式大量重載、以消耗記憶體的方式減少對硬碟的通路等。你可能要花掉數個工程師個把月的時間,才得以将架構重新規劃,程式全面重載,或許花費如此的人力成本還不如直接更新裝置,但性能調校的總體成本(total cost)并不容易計算。
筆者遇到的大部分狀況是管理者會挑眼前最節約成本的事情先做。一般來說,就是要工程師着手調架構,可能是資料庫的設計,也可能是程式代碼重載,忙了個把月後聲明失敗,最後還是花錢買機器。這種僅看目前最低成本的做法有幾個弊端:
使用者苦等一兩個月,最後還是換機器,他們會覺得工程師能力不足。
實際上浪費了人力成本。
一陣子後,性能問題又再度浮現。
在動手調校前應該對整個系統的各個瓶頸點了然于胸,各花多少成本可以解決,而該瓶頸調整後,整體系統性能可以提升多少。以筆者曾調校的系統為例,整體設計是用IE呈現IIS執行ASP的結果,ASP 調用COM+,COM+通路SQL Server。系統剛上線時,總響應時間是7秒鐘,但使用者可以接受的時間是3 秒鐘。程式中,個别的時間消耗是IE花費2秒鐘(因為前端PC老舊,而執行操作很複雜),ASP 處理時間0.5 秒鐘,COM+處理時間4秒鐘,SQL Server處理時間0.5秒鐘。
前端PC 數量太大,要更新成本太高。是以,大家都覺得先調後端吧,這時就算工程師花了九牛二虎之力,将三種伺服器的性能都提升一倍,也就是讓原來各伺服器處理時間的總和5秒鐘降為2.5秒鐘,但系統整體時間還是要4.5秒鐘。
使用者罵了一個月之後,在不準更改功能的窘境下,還是要更新前端PC,這時大家就難堪了。是以,事前的整體評估很重要,告知使用者能期待什麼?最後底線是什麼?才有可能讓大家都接受調校的結果。
性能的基線應該都是可以量化的,例如,響應時間、機關時間可執行的批處理數量、機關時間可以處理的資料量、同時上線人數等,都可以求出最大值、最小值、平均值、總數等。針對要調校的目标,先擷取資料後,才可以評估調校的方向是否正确。另外,對系統各環節的性能極限應盡可能地評估一下,不要耗了極大的功夫,才發現其實早已經把某一部分發揮到極限了,再怎麼做都不可能提升多少性能,這時你可能需要變更使用者需求、系統架構或必須更換軟硬體。
有些值是目前可以算出來的,例如,直接将使用者通路資料的T-SQL語句目前執行一遍,可以看出執行該語句的時間,在SQL Server本機上通過管理工具執行一次,在遠端網絡上再執行一次,可以約略知道網絡是否有影響等。但某些資料可能要特别建立一些環境來測試,例如,沒有使用者,空機的時候某個工作的執行效率如何?有多人上線時,又是如何反應?原本某個工作每秒鐘可以完成多少次,加上什麼運作程式後,每秒鐘隻剩幾次等。
另外,如壓力測試時,要仿真多大的資料量,多少人同時上線等,建立這些基線的資料就較為困難,因為仿真的環境要盡量與真實相同。因為不同的資料模型,SQL Server 會建立不同的執行計劃,若是以随機數産生的資料,往往與真正的資料類型不符,使索引判斷、選擇如何做Join等都會大不相同。
這些基線的資料應該越詳盡越好,不要泛泛地取些值就拿來比較。筆者碰過一位工程師拿着代表某大型系統執行性能的4張圖,上面标着中央處理器、主存儲器、硬碟與網絡,各有着一條彎彎曲曲描述性能的線,除了記憶體的線長時間在天上之外,其餘的都不高,他就有了結論:記憶體要加大。當然,你讓不懂資訊技術的路人甲看這4張圖,跟他解釋圖形的意義,問他要如何調性能,他也會說要加記憶體,因為就隻有這張圖看起來和其他3張長得不一樣。
如果公司的錢用不完,這樣的調校似乎就足夠了,全部都靠擴大硬體來提升性能。但就前述的現象,可能要問的是,記憶體與硬碟緩存盤交換是否頻繁,資料緩存區的高速緩存擊中率(cache hit ratio)是否低于90% ,以進一步确認是否為記憶體不足才拖慢整體性能。說不定是資料庫鎖定,也說不定是程式有Bug造成記憶體遺失(memory leak),或是程式本身的Bug造成性能不足等。
若真的是記憶體不足,是否還可以調校?說不定是資料庫系統的設定一開始要占用極大的緩存區,是以,大部分的記憶體都被它拿走,但整體來說并沒有有效使用記憶體 。是以,哪個程式吃掉了大部分的資源?誰是主要調校的目标?什麼樣的方向或指針代表調校有效?諸此種種都應該落到文字上,如此可以整理較為清晰的思路,并有可讨論的交集,否則一堆沒有共識的專家,恐怕隻會衆說紛纭,皆能證明不是自己的錯,但禍首是誰卻說不出來,最後落到會而不議,議而不決的窘況。
這些落于紙上的目标應越明确越好,例如上述的情況,若目标是 “我想要調低記憶體的使用率,因為它的值太高了”就不如“我想要調低某個程式開始擷取記憶體的設定,因為它可能吃掉太多的記憶體,但實際沒有用到這麼多,而其他的應用程式沒有足夠的記憶體,導緻整體系統性能不佳”。後者的描述有目标,且可以比較,因為實際調整後可以觀察調低記憶體的程式執行起來是否有問題,整體的性能與沒調整前是否有差異。
除了以文檔描述基線、調校的目标外,還可以以文檔描述所用的工具,如評估性能的程式、真實應用程式的片段功能、各種資源的性能監視程式、壓力測試程式等。同時,有越詳細的步驟越好。性能調校可能是一再的錯誤嘗試,因為大部分的狀況都是撲朔迷離的,無法一眼看出問題所在,需要改改這個,看看是否比較好,再修修那個,看看結果如何。若沒有文檔記錄,你可能會在性能調校的大迷宮中打轉,做一些類似而重複的事情,但總理不出頭緒。
嘗試列出系統中各個元件合理的性能消耗,可以幫助你理清整個系統通路中,各個元件所占的性能消耗比例,哪些部分有可以調整的空間。另外,再搭配調整該部分的成本有多高,讓你了解調整的優先級,并對系統的極限有更佳的認識。