記錄一次系統優化


春節期間,和朋友一起做了一個關於物流行業的系統優化,在此記錄一下優化過程及過程中遇到的問題,用以備忘,同時分享給有類似需要的朋友.

首先交代一下背景:

  1. 數據庫采用MS SqlServer 2008 R2, 數據庫物理文件大小為150G.
  2. 系統大部分報表采用存儲過程實時統計,前台系統通過視圖實現.
  3. 快遞物流行業,平均每天產生8000票新快遞單,關系到單據網點及狀態的流轉,每票快遞單表現在數據庫中大概會產生8張新的其他跟蹤單據.
  4. 數據庫服務器: 8核CPU 256G 內存 1T固態硬盤, Windows Server 2008 64位操作系統.
  5. 正常時段(早6點-凌晨3點),平均實時在線用戶數為4000+,閑時(凌晨3點-早6點)平均在線用戶數為900+.
  6. 正常時段數據庫服務器,CPU 占用率一直穩定徘徊在70%-90%的高位.
  7. 正常時段,系統功能使用異常卡頓,報表基本上出不來結果,數據庫常常發生死鎖.

在了解了以上背景后,我們對系統分別做了以下調整:

  1. 和核心業務無關的數據移除到另外的數據庫, 如短信記錄, 人員檔案等.
  2. 優化索引.
  3. 核心業務的數據表采用按時段做分區表.
  4. 核心業務的數據提交采用根據操作日志按順序合並后統一提交,而非直接操作原始數據庫.
  5. 數據庫讀寫分離.
  1. 寫在開始之前,介紹幾個常用的DBA命令.
    首先, 在做數據庫優化的時候,我們必須得知道為何要優化以及優化的方向,以及調整的方向,了解以下的幾個常用數據庫命令可能會對我們快速的分析和解決問題起到一定的幫助.
    • a). 查看某段sql/存儲過程的詳細執行時間及執行的詳細步驟:

      SET STATISTICS PROFILE ON 

      SET STATISTICS IO ON 

      SET STATISTICS TIME ON  GO /*--你的SQL腳本開始*/ SELECT * FROM tb /*--你的SQL腳本結束*/ GO SET STATISTICS PROFILE OFF

      SET STATISTICS IO OFF 

      SET STATISTICS TIME OFF

      通過設置STATISTICS我們可以查看執行SQL時的系統情況。選項有PROFILE,IO ,TIME。介紹如下:
      SET STATISTICS PROFILE ON:顯示分析、編譯和執行查詢所需的時間(以毫秒為單位)。
      SET STATISTICS IO ON:報告與語句內引用的每個表的掃描數、邏輯讀取數(在高速緩存中訪問的頁數)和物理讀取數(訪問磁盤的次數)有關的信息。
      SET STATISTICS TIME ON:顯示每個查詢執行后的結果集,代表查詢執行的配置文件。

    •   b).查看某個表的索引情況 : sp_helpindex 表名  .
    •   c).查看表存儲的碎片情況: DBCC ShowContig (‘表名’) .
    •   d).整理表上的索引碎片: DBCC IndexDefrag .
    •   e).重建某個表的索引: DBCC DBREINDEX (‘表名’) .
    •   f). 查看某個表的數據量及所占磁盤空間: sp_spaceUsed ‘表名’.
    •   g). 收縮某個文件組: DBCC ShrinkFile .
    •   h). 修改數據庫服務器名稱: select @@ServerName ;/ sp_dropserver  ‘oldServerName’;/ sp_addserver ‘newServerName’,'LOCAL' ;
  2. 索引優化.
    在這里, 限於篇幅,不想談論索引的概念問題.只提出幾個建議以供大家參考.
    •   a).盡量不要將寶貴的聚集索引定義在毫無順序的主鍵上, 改為定義在有順序且較常用的查詢條件列上, 如 本案例中 將業務表聚集索引由 ”guid主鍵 ”改為了 ”收件時間 ”.
    •   b).合理應用 ”包含索引”,當有多個大表關聯的時候,若需要獲取的關聯表數據列不多,可嘗試在需要關聯表的關聯字段索引上創建查詢返回字段的包含索引. 此場景下會起到非常明顯的效率提升.
    •   c). 合理的利用 “組合索引”,當關聯查詢的時候,若關聯的條件有多個,或者在查詢的時候,有多個組合條件,且這種組合條件常常都需要一起出現的時候,可嘗試將這幾個組合條件創建一個組合索引.
    •   d).盡量不要在有較多重復值的列上創建索引,因為即便創建了,也不一定能利用上,大多時候僅徒增存儲空間.
    •   e). 時刻關注表索引的碎片情況,通過 “DBCC ShowContig (‘表名’)”命令查看碎片情況及索引命中率,當比值出現較低情況下, 建議使用 “DBCC DBREINDEX (‘表名’) ”命令重建其索引,此步驟可嘗試創建一個作業,自動檢查.
  3. 表分區.
    在本案例中,幾個關鍵的業務表數據量已經達到了千萬/幾十G的數據量,在這個數據量下,每次查詢都變得異常慢,又特別是在這種高並發的狀態下,服務器已經不堪重負,前文背景中已經提到,這么高配置的服務器下, CPU還長時間負荷在70%-90%,於是我們嘗試着引入分區表來解決這個問題.在本案例中,以運單記錄表為例.
    •   a). 新建文件組,文件組為一組物理文件的邏輯包含關系,本處我們分別對於運單,財務,基礎數據,其他資料分辨創建了對應的文件組.
    •   b). 選擇分區列,及創建分區索引,根據業務場景我們選擇了”收件時間”,首先將原主鍵的聚集索引改為普通索引,其次將收件時間列轉為了聚集索引.
    •   c). 創建分區函數,根據數據量及實際需求合理確定分區區間規則,常常查詢請求一般都在一個季度內,所以我們在這里將分區區間定為按季度.即每三個月創建一個分區,並將數據分區的數據轉移到指定的文件組中
    •   d). 在程序和存儲過程中,檢查無分區列條件的sql, 將分區列條件補充上,使其每次查詢都盡量能預先知道數據的分區位置.

         通過以上的表分區及索引優化步驟后,我們的系統在性能表現上有了很明顯的提升,服務器CPU資源占用已經有效的下降到了40%-55%樣子,通過介紹的第一個命令查看得知,相同的查詢已經大大的降低了IO開銷.
         但問題往往並不是一帆風順的, 第二天有人反饋,系統中的某些功能變得奇慢無比,根本就沒有辦法使用,比優化前更加的慢了, 是的,你沒有聽錯, 有些功能比分區后更加的慢, 按常理來說應該不應該才對, 結果仔細檢查,發現比較慢的地方基本由兩方面原因:查詢條件里面沒有分區列字段”收件時間”條件 及 部分數據的”收件時間”為null,查詢條件中無”收件時間”到好說,根據業務場景,補上這個條件即可.
         對於有的數據初始狀態”收件時間”為null的情況,結果某些操作后,該單據的收件時間才會錄入的情況,引起慢的問題卻並不容易解決,因為操作前后這個收件時間不一致,該條數據應該會落在兩個不同的分區里面, 並且很可能是跨物理文件的,根據業務場景,發現初始狀態收件時間為null的情況僅出現在特定的場景下, 於是在此過程中,我們通過引入一個中間表, 將這種特定場景下的數據優先產生在一個新的臨時業務表中,待后續中的登記了收件時間后,再將該數據轉移到正式的業務表中.
        至此,由於分區引起的問題順利的解決.
  4. 更新頻繁的表 ”采用操作日志更新”來代替 ”直接操作原始數據庫”. 
         因為高並發 ,數據操作入口較多, 數據庫常常發生死鎖,特別是對於運單表的處理尤為突出.針對這個情況,我們引入了操作日志表的概念, 然后后台新起一個服務, 定時將這個操作日志按順序合並,將合並后的結果在更新到運單業務表,這樣做就將運單數據的更新入口由系統中的各個並發點統一收歸到這個后台服務中,也就有效的避免了這個表的死鎖情況.
  5. 數據庫讀寫分離.
           其實經歷了以上幾步后,系統已基本起死回生了, 穩定運行了幾天基本上大部分業務都已經能正常開展, 唯獨實時統計的報表比較費時,為了分散主要報表的數據庫訪問壓力,我們嘗試了將數據庫做讀寫分離,在本案例中,數據庫同步我們采用數據庫自帶的復制技術,在這里將讀寫分離的關鍵步驟羅列在此,以供有需要的朋友參考.
    •   a).准備從庫服務器,本處我們使用了和主庫一樣的環境, MS Sqlserver 2008 R2 + Windows Server 2008 64 bit.
    •   b).在主庫服務器上安裝ftp服務器,本處我們使用操作系統自帶的ftp服務器,怎么開啟操作系統的ftp服務,各位可自行谷歌.
    •   c).將主庫數據庫服務器設置為允許通過機器名登錄(因為從庫訂閱的時候,只能使用服務器名稱來連接,不能使用IP地址).
    •   d).將主庫和從庫服務器的 Sql Server 代理 服務開啟.
    •   e).在主庫服務器上新建數據庫發布.本案例中的發布類型選擇為”事務發布”並設置為將快照文件通過ftp服務傳遞.至於幾種發布類型的區別以及發布的創建詳細步驟,園子里面有很多人討論過,本處就不做深入展開了.
    •   f).在從庫服務器上新建數據庫,並創建主庫服務器的數據訂閱,注意此處如果使用主庫的服務器名稱不能正常訪問,可嘗試在系統的etc文件中增加上IP的別名映射.
    •   g).可通過復制監視器查看數據的復制狀態.正常運行兩天過程中, 密切監視數據的同步狀態,發現一切正常.
    •   h).調整程序, 增加從庫的數據庫連接,將除具有實時性質讀取之外的數據庫訪問接口,調整為使用從庫數據庫連接.
    •   i).在一主一從數據庫模式正常運行4天后,我們又嘗試着將其數據庫調整為一主多從的模式.
  6. 引入Web系統負載均衡.
          關於負載均衡,有很多的實施方案, 甚至如果你們公司不差錢,可以引入F5這樣的土豪利器來處理.在本案中,我們選用了微軟的NLB, 這個組件已經集成在了Windows Server 版的操作系統中,關於NLB的使用,園子里面有很多大神的談論過,或可參閱http://www.iis.net/learn/extensions/configuring-application-request-routing-(arr)/achieving-high-availability-and-scalability-arr-and-nlb,在此,本文就不深入闡述了.
  7. 后記.
              經過這一系列優化后,系統已經表現得比較良好,本階段的優化也即將告一段落,當然隨着時間的推移, 系統肯定會遇上更多的問題,或許這僅是該系統優化的一個開始. 當然每個生產環境都或多或少不一樣,以上的步驟不一定適合每一個看官所遇到的問題,但或許能給你提供一個類似問題的思路.最后補充上這個系統最后優化完的部署結構草圖作為本文的收尾,限於編輯方便,此部署圖用word簡單的畫了一下,各位看官莫怪.
    .部署圖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM