第一節 影響效能的因素
一般來說我們說sqlserver出現效能問題時,主要指的是:
響應時間:提交請求到收到第乙個響應位元組的第乙個字元的時間間隔;
吞吐量: 單位時間內處理的批數量;
可擴充套件性: 當上述兩個指標不夠理想時,是否能夠簡單的通過新增新的伺服器來滿足。scale out(相對於scale up);
當dbms出現問題時,對運維來說可能是監控出現明顯的有別於歷史曲線的異常波動,例如cpu高,鎖上公升,io異常上公升等,對於系統使用者來說則是系統響應明顯變慢。
從全域性來看,能夠影響資料庫效能的因素有很多,概括的來說可歸結於如下幾個方面:
應用程式的體系結構: 乙個好的架構很多時候都能最大的利用伺服器,資料庫的潛力;不好的,額,看看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如下:
1view codeselect
count(1) as
workers_waiting_for_cpu, t2.scheduler_id
2from sys.dm_os_workers as t1, sys.dm_os_schedulers ast23
where t1.stat =
'runnable
'and t2.scheduler_id <
2554
group
byt2. scheduler_id56
7select
sum(signal_wait_time_ms)
8from 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.
SQL Server技術內幕筆記合集
microsoft sql server 6.5 技術內幕 筆記 microsoft sql server 2005技術內幕 t sql查詢筆記 microsoft sql server 2005技術內幕 儲存引擎筆記 microsoft sql server 2005技術內幕 查詢 調整和優化筆記...
SQL Server技術內幕筆記合集
microsoft sql server 6.5 技術內幕 筆記 microsoft sql server 2005技術內幕 t sql查詢筆記 microsoft sql server 2005技術內幕 儲存引擎筆記 microsoft sql server 2005技術內幕 查詢 調整和優化筆記...
MySQL技術內幕
innodb儲存引擎是事物安全的儲存引擎。innodb儲存引擎有多個記憶體塊,這些記憶體塊組成乙個很大的記憶體池,負責如下的工作 後台執行緒 innodb儲存引擎是多執行緒模型,因此他有多個不同的後台執行緒,負責處理不同的任務。記憶體日誌檔案 記錄mysql對某種條件做出響應時的檔案,如錯誤日誌檔案...