記得在自己學習資料庫知識的時候特別喜歡看案例,因為最佳化的手段是容易掌握的,但是整體的最佳化思想是很難學會的。這也是為什麼自己特別喜歡看案例,今天也開始分享自己做的最佳化案例。
最近一直很忙,部落格產出也少的可憐,今天整理了一下自己做過最佳化或各種方案的客戶已經超過100家了,今天分享的案例算是在這些客戶中比較典型的了!沒有什麼高大上都是常見的問題!在之前的部落格中都有過提及,那麼本篇我們就結合之前的技術點來看看這個案例。學習最佳化手段的看官們可以參見我的最佳化系列:
系統環境
首先我們來看一下這個系統配置及現狀,為什麼說這個客戶經典?那就是因為這個客戶已經達到可以慢的地方都慢,不該慢的地方也慢!
首先這是一套醫院的HIS系統,慢到什麼程度呢?各種功能卡死不管是交款、醫囑、開藥一些列幾乎所有的功能都慢。但是卡慢的現象只出現在上午的高峰期!
先來看看系統配置 :
資料庫版本是SQL SERVER 2008R2,資料量大概1個多T,伺服器64CPU 、128G記憶體,伺服器只執行資料庫。
咋一看伺服器確實有點老了,資料量也大了,記憶體和CPU什麼的明顯不夠用了!
資料庫指標
那麼我們再看一下資料庫的一些表象:
每秒請求數量:
語句執行情況:
等待情況:
等待時間:
CPU指標:
記憶體一些指標:
磁碟佇列:
-------------------還很多指標就不一一展示了------------------
看到這些基本的指標,除了慢你能看出什麼?問題出在哪裡?怎麼樣快速解決?能有一個最佳化的步驟呈現在眼前麼?
最佳化階段一(常規最佳化)
很多時候系統慢要究其原因,難道上線時候就這麼慢?那不可能,廠商根本無法交付的!那麼問題來了,什麼時候開始慢的?對系統做過哪些調整?
簡單的調研開始...給我的只有不到半天的調研時間...得知的基本問題就是系統在最近一月增加了很多功能,有上線了很多其他系統介面!
那麼直接就搞新功能、新程式介面語句? 我認為並不是這樣,從一名資料庫從業人員來說,看到這樣的系統一定要先解決大面積等待問題!個人經驗來看很多系統大面積等待解決系統會有個很大的提升和改善!
配合一些常規的調優手段階段一開始了,主要給系統大面積建立影響高開銷大的索引,調整系統引數,最佳化tempDB、開啟快照讀等....具體不細說了,前面系列文章中都有!
預期:
一般系統上面一輪最佳化會有明顯的改善,我認為這一輪以後系統會明顯變快,語句CPU會下降到70%左右,記憶體壓力也會有所減少。
結果:
自信滿滿的我第二天去了各個科室....部分功能依然超時還是各種慢...CPU依然90%以上,記憶體壓力依然明顯。但是收集的資料來看,長時間語句數量已經大幅降低,系統等待阻塞情況也明顯好轉。
最佳化前
最佳化後
最佳化前
最佳化後
最佳化階段二(針對語句)
再次分析解決大面積語句阻塞的系統,發現現在的情況,主要有如下幾個:
- 由於記憶體不足導致的IO壓力。
- 系統CPU依然彪高。
- 部分功能語句依然慢,消耗的資源很高。
再次對系統調研:
- 哪些功能慢,執行的語句是什麼。
- 系統的介面語句問題。
- 系統中還有哪些消耗資源高的語句,是否能最佳化。
調研後,我遇到了最常見也是最大的問題: 語句慢由於程式!很多人看到這會說程式慢就改唄,那有啥問題? 問題就在於你來做最佳化直接了當的和人家開發人員說你程式太爛必須改!如果你是程式開發人員你會有什麼樣的反應?
他會說:對不起,影響太大改不了!
那麼這個最佳化專案黃了,或者你要付出更大的代價繞過這樣的問題。
分析中發現程式使用了大量各種自定義函式,有一定經驗的人都應該知道,語句在篩選的列上使用函式是沒有辦法使用索引查詢的,這樣相對於這種單表資料就幾百甚至幾千萬的表,是何等的災難!但是不能冒然突出修改程式,那還能怎麼最佳化呢?大概分析後得出結論,程式主要消耗在幾部分:
- 部分業務功能語句慢。
- 介面語句慢(主要是檢視,供其他程式呼叫)。
- 還有報表程式。
針對第一部分在不能改程式的情況下,嘗試新增計劃嚮導改變語句執行情況;
針對第二部分修改介面檢視,包括替換掉函式、新增索引等;
針對第三部分報表這東西不是短期就可以最佳化的,所以再原有映象的方案上新增快照,實現了簡單的讀寫分離,直接分走;
語句最佳化的效果:
最佳化前
最佳化後
最佳化前
最佳化後
預期:
90%消耗高的語句都得到了最佳化,系統應該可以快起來了,CPU、記憶體指標也應該正常了!
結果:
語句的消耗和時間都降下來了,系統卡慢現象有明顯好轉,但是CPU依然90%以上、記憶體壓力依然明顯,磁碟佇列還是很高!系統效能問題依然存在。
最佳化階段三(深入指標分析)
經過前兩個階段的最佳化一般系都會明顯好轉,並且指標正常,這也是前面提到的可以慢的地方慢已經解決,那麼為什麼CPU、記憶體壓力沒有緩解?難道真的是64CPU、128G記憶體不能支援了?需要加記憶體換CPU?難道要做負載均衡?各種拆分?
CPU分析
首先我對CPU壓力進行了分析,綜合語句的CPU消耗和CPU的表象來看,很大一部分應該不是語句執行消耗的!那麼伺服器上確實也沒有跑其他程式,CPU資源哪裡去了?
看看這個計數器:
SQL的編譯次數高峰時間段達到每秒2000多次!很多書上寫過,相信很多看官也知道,語句不引數化會給CPU造成壓力,這就是個鮮活的例子!那麼解決辦法也是比較粗暴,程式無法修改那麼就在資料庫上開啟強制引數化。
看下效果:
我想不用多說什麼了!
記憶體分析
看到了CPU的現象那麼記憶體的問題也有眉目了,這麼多編譯即席查詢,首先看一下記憶體中快取了那些資料:
SQLOPTIMIZER Singlepage佔到了80多個G,而在查詢資料頁的快取只有20個G,而且仍然在被不斷壓縮,那麼記憶體沒壓力就怪了!這個SQLOPTIMIZER Singlepage嘗試了一下是無法透過DBCC FREExxxxx的操作釋放的,所以在半夜直接重啟了SQL 服務!將近2年沒有重啟的SQL服務就這麼折在我的手裡了!
重啟後頁生命週期:
記憶體這個問題,不知道是不是微軟的一個小BUG,查詢計劃的快取個人理解不會一直壓榨資料快取的,客戶的資料庫沒有補丁,但是查閱08的各個補丁也沒有找到相關問題的修復。
也請遇到過或瞭解的朋友給點提示!
預期:
語句已經最佳化,阻塞情況也被解決,CPU、記憶體、磁碟壓力也沒有了,系統肯定快起來了!
結果:
系統快起來了!
總結 : 文章只是簡單的描述了一下某醫院HIS系統的最佳化過程,當然一週的工作僅僅透過一篇文章寫出全過程細節必然不那麼詳盡,還望看官們見諒!
整個的最佳化過程是程式只修改了2條語句,其他都是透過資料庫最佳化手段完成。而且沒有新增任何硬體資源!
最佳化過程主要分為:
- 系統整體調研 :和科室使用者溝通慢的情況,系統最近變更情況,並收集資料。
- 常規最佳化 : 調整資料庫引數配置,新增索引,解決阻塞。
- 再次調研:系統慢功能,慢語句。
- 針對語句最佳化:寫法不足,是否缺失索引,是否能加提示、計劃嚮導等
- 整體壓力是否緩解:如果仍然壓力很大找到瓶頸,是否可以解決?如果不能解決才考慮新增硬體或選用分離、分離等方案。