第一節 影響性能的因素 數據庫
通常來講咱們說SQLServer出現性能問題時,主要指的是:服務器
響應時間:提交請求到收到第一個響應字節的第一個字符的時間間隔;網絡
吞吐量: 單位時間內處理的批數量;架構
可擴展性: 當上述兩個指標不夠理想時,是否可以簡單的經過添加新的服務器來知足。Scale Out(相對於Scale up);運維
當DBMS出現問題時,對運維來講多是監控出現明顯的有別於歷史曲線的異常波動,例如CPU高,鎖上升,IO異常上升等,對於系統使用者來講則是系統響應明顯變慢。異步
從全局來看,可以影響數據庫性能的因素有不少,歸納的來講可歸結於以下幾個方面:ide
應用程序的體系結構: 一個好的架構不少時候都能最大的利用服務器,數據庫的潛力;很差的,額,看看12306就知道了,相信在給他們1W臺服務器他們也搞很差。函數
應用程序設計:我就看到過曾經有兄弟傻乎乎的把幾百萬的用戶信息一次加載到內存中。固然實際狀況大都比這個要更爲複雜;程序設計包括物理設計和數據庫模型設計,物理設計是指數據文件在存儲介質上的分佈,例如temp數據庫最好能放在獨立高速的磁盤;日誌和數據最好能放在不一樣的磁盤上避免IO競用; 將頻繁使用的數據表分散到不一樣的磁盤一樣是避免IO競用。數據模型設計則主要是範式的適用和選擇,更高的範式意味着更高的寫入更新一致性和最低的查詢性能。企業級開發和互聯網開發有大相徑庭的選擇。企業開發可能儘量的保證數據一致性即便這將致使更爲複雜的程序結構和更復制的鏈接查詢。 可是互聯網行業則更看重可用性和高吞吐量,經過異步和補償機制保證延遲一致性和最終一致性。這就能夠將範式降到較低的級別上。工具
事務和隔離級別: 將SQLServer設置在一個比較合適的隔離級別上不是容易的事,大多數咱們將其放在默認的級別上(讀已提交)上就夠了,對於特殊須要的在個別的加上提示(ULock/NoLock等),務必保證不持有當前沒必要要的數據。儘可能將持有的鎖的力度降到最低(這裏不是說行鎖就比頁鎖要好,大量的行鎖一樣會帶來負面的影響。沒有特殊緣由和實際的測試不要輕易的升級/降級鎖的粒度。大部分時候SQLServer鎖都能選擇合適的粒度)。事務隔離機制包括:讀未說起,讀已提交,可重複讀,串行化。這個更詳細的本身去Google就行了,此處略。性能
Transact-SQL: 完成一樣的邏輯處理,使用不一樣的SQL語句和不一樣的謂詞,最終的性能差異可能會差很大,有的時候甚至超出你的想象。 這歸結於SQLServer的查詢優化器其實還不夠智能,當他認爲優化到足夠好的時候,處於成本考慮就不會繼續的優化下去了。 我我的碰到過的一個例子就是當我把一個很糾結的多表Join查詢改爲一個井井有條相關子查詢時,執行時間一會兒從40s+ 降到了20ms。這個當時我本身都很意外。 比對兩次生成的執行機會,發現優化的執行計劃很一樣簡潔,Index Seek 後直接 Merge Join了,而以前的執行計劃則是查詢優化器幾乎沒有任何的優化,直接按照SQL的書寫順序一路HashJoin到底。
硬件資源: 沒什麼可說的,上述幾條沒有優化的餘地的時候,就須要考慮是否升級硬件了,網卡是否是仍是10M,硬盤是否是仍是5400轉的,內存是否是過小等等。固然若是你的用戶從1000~100W了也真該考慮是否是把服務器整個換成更高配的機器了。
SQLServer配置:不少時候若是業務的數據交換量真的很大,不管如何優化都沒有改善的時候能夠看下SQLServer的一些配置上是否有改善的餘地,這點上必定要謹慎且要有住夠的測試結果支撐。不然可能拔苗助長。 微軟的一向風格,通常來講,默認的就是最好的。這裏須要特別說明的有兩點,一:工做進程在X86,X64,IA64上分別消耗512K,2M,4M內存。且最大進程數受CPU數量有關。全部並非越大越好。32位CPU個數與最大進程數的關係是:4,8,16,32個分別對應最大進程數爲256,288,352,480; 64位處理器則翻倍。 這個對應的就是最大並行批處理的個數了。 若是有較多的需長時間運行的批處理則考慮將最大進程數適當調高。 二: SQLServer最大和最小可用內存,請務必不要就將CPU和內存所有分配給SQLServer,不然一旦SQLServer宕了,服務器也就宕了,補救都沒辦法。
第二節 故障排查概要
對於開發人員來講故障可能就是指Bug,系統崩潰等,對於運維和BI來講可能異常的數據波動就意味這故障。固然不能等何時系統真正完蛋了,纔去着手幹活。通常來講都有各類各樣的監控系統在跑。監控各類指標CPU,內存,IO,網絡等等。 按照歷史基線,一旦偏離歷史值或者某個絕對值。就發出去預警,接着優化的活就來了。
SQLServer的各類監控數據主要來自與一下幾個方面:
系統監控器: 這個是基於輪詢的。開銷取決於計數器的數量和頻率。總的來講開銷蠻大的,幾乎沒見有實際的項目中用這個。
SQLServer性能分析器: SQLSERVER跟蹤的一個圖形界面。用來監視SQLServer實例,結果輸出到文件或者數據表。性能分析器基於事件,基本上不會丟掉任何指定要監視的事件。 開銷一樣取決於監視的事件類型和事件發生的頻率。對性能有必定影響。
數據庫引擎優化顧問(DTA):這個只能作靜態分析,也許系統測試的時候能夠跑跑看,而後提些建議之類的。實際運行中則沒什麼用。
DBCC命令:數據庫控制檯命令,大多數用來檢測數據庫的一致性。監控內存,日誌,CPU的使用狀況等大方面指標。不能反映實際的性能問題。
動態管理視圖/函數(DMV,DMF):這個纔是監視和分析的重頭戲,經過各類視圖/函數能取得幾乎全部你要的檢測和運行數據。DMV設計和系統視圖和系統函數相同,能夠經過跨視圖的Join得到各種數據。 一樣DMV/DMF 也是基於輪詢的,可能會丟掉時間臨界點的數據。
有了這些工具就能得到運行時的各種監控數據,一旦收到警報就能着手進行故障的排查。對DBA來講,活來了。
通常來講,大部分的SQLServer性能故障的排查步驟不十分相似,一旦一個故障出現,就意味着在CPU,內存,IO,網絡等一個或多個資源上出現瓶頸。
CPU: 在以提交的批處理總會處於運行中,可運行,掛起三種狀態中的一種。這個能夠參考線程的概念。後臺實際每一個批處理對應的線程。 注意一點:可運行表示等待CPU,掛起表示等待資源,如鎖,IO。 因此鎖若是一旦有大量的可容許意味着CPU瓶頸,大量的掛起這說明鎖太多了。 上述指標均可以經過特定的DMV(Sys.dm_os_workers,sys.dm_os_schedulers,sys.dm_os_wait_stats等)來查詢。查詢可運行狀態的工做進程數和可預先狀態下花費的時間SQL以下:
1 SELECT COUNT(1) AS workers_waiting_for_cpu, t2.scheduler_id 2 FROM SYS.dm_os_workers as t1, sys.dm_os_schedulers AS t2 3 WHERE t1.stat = 'Runnable' AND t2.scheduler_id < 255 4 GROUP BY t2. scheduler_id 5 6 7 SELECT SUM(signal_wait_time_ms) 8 FROM sys.dm_os_wait_stats.
SQLServer 一樣提供了DMV的圖像化界面。能夠查看單個指標的圖形化顯示。
一把來講CPU高主要緣由是: 生成低效的查詢計劃,統計值更新或其餘緣由致使的重編譯。能夠衝這些方面着手排查。固然若是你每次搞個上百萬數據的Join或者函數逐行處理也會致使CPU高。
內存和IO瓶頸: 這兩個交容易排查,且有關聯性,若是內存壓力較大則會致使大量的IO產生。通常來講出現這兩個問題直接經過DMV查找消耗內存和IO最高的批處理就對了。
tempdb: 臨時數據庫的瓶頸比較少見,可是一旦出現會比較致命,它見致使整個SQLServer實例的全部DB的性能出現問題。 通常來講只要不在臨時數據庫上大量的建立臨時對象和數據就不會出現。 檢測方式和其餘DB相似,一樣可使用DMV和系統監視器來檢測具體的瓶頸。
阻塞: 這裏的阻塞不只僅是指邏輯鎖,雖然鎖是最多見的阻塞緣由。 還包括IO等待,內存分配等待等等。對於的DMV主要是sys.dm_os_wait_stats.