概述 當你的SQL Server數據庫系統運行緩慢的時候
你或許多多少少知道可以使用SQL Server Profiler(中文叫SQL事件探查器)工具來進行跟蹤和分析
是的
Profiler可以用來捕獲發送到SQL Server的所有語句以及語句的執行性能相關數據(如語句的read/writes頁面數目
CPU的使用量
以及語句的duration等)以供以後分析
但本文並不介紹如何使用Profiler 工具
而是將介紹如何使用read
trace(有關該工具見後面介紹)工具結合自定義的存儲過程來提綱挈領地分析Profiler捕獲的Trace文件
最終得出令人興奮的數據分析報表
從而使你可以高屋建瓴地優化SQL Server數據庫系統
本文對那些需要分析SQL Server大型數據庫系統性能的讀者如DBA等特別有用
在規模較大
應用邏輯復雜的數據庫系統中Profiler產生的文件往往非常巨大
比如說在Profiler中僅僅配置捕獲基本的語句事件
運行二小時後捕獲的Trace文件就可能有GB級的大小
應用本文介紹的方法不但可以大大節省分析Trace的時間和金錢
把你從Trace文件的海量數據中解放出來
更是讓你對數據庫系統的訪問模式了如指掌
從而知道哪一類語句對性能影響最大
哪類語句需要優化等等
Profiler trace文件性能分析的傳統方法以及局限 先說一下什麼是數據庫系統的訪問模式
除了可以使用Trace文件解決如死鎖
阻塞
超時等問題外
最常用也是最主要的功能是可以從Trace文件中得到如下三個非常重要的信息
運行最頻繁的語句
最影響系統性能的關鍵語句
各類語句群占用的比例以及相關性能統計信息
本文提到的訪問模式就是上面三個信息
我們知道
數據庫系統的模塊是基本固定的
每個模塊訪問SQL Server的方式也是差不多固定的
具體到某個菜單
某個按鈕
都是基本不變的
所以
在足夠長的時間內
訪問SQL Server的各類語句及其占用的比例也基本上是固定的
換句話說
只要Profiler采樣的時間足夠長(我一般運行
小時以上)
那麼從Trace文件中就肯定可以統計出數據庫系統的訪問模式
每一個數據庫系統都有它自己獨一無二的訪問模式
分析Profiler Trace文件的一個重要目標就是找出數據庫系統的訪問模式
一旦得到訪問模式
你就可以在優化系統的時候做到胸有成竹
心中了然
可惜直到目前為止還沒有任何工具可以方便地得到這些信息
傳統的Trace分析方法有兩種
一種是使用Profiler工具本身
比如說可以使用Profiler的Filter功能過濾出那些運行時間超過
秒以上的語句
或按照CPU排序找出最耗費CPU的語句等
另一種是把Trace文件導入到數據庫中
然後使用T
SQL語句來進行統計分析
這兩種方法對較小的Trace文件是有效的
但是
如果Trace文件數目比較多比較大(如
個
MB以上的trace文件)
那麼這兩種方法就有很大的局限性
其局限性之一是因為文件巨大的原因
分析和統計都非常不易
常常使你無法從全局的高度提綱挈領地掌握所有語句的執行性能
你很容易被一些語句迷惑而把精力耗費在上面
而實際上它卻不是真正需要關注的關鍵語句
局限性之二是你發現盡管很多語句模式都非常類似(僅僅是執行時參數不同)
卻沒有一個簡單的方法把他們歸類到一起進行統計
簡而言之
你無法輕而易舉地得到數據庫系統的訪問模式
無法在優化的時候做到高屋建瓴
綱舉目張
這就是傳統分析方法的局限性
使用下面介紹的Read
trace工具以及自定義的存儲過程可以克服這樣的局限性
Readtrace工具介紹以及它的Normalization 功能 Read
Trace工具是一個命令行工具
使用Read
Trace工具可以大大節省分析Trace文件的時間
有事半功倍的效果
Read
Trace的主要工作原理是讀取Trace文件
然後對語句進行Normalize (標准化)
導入到數據庫
生成性能統計分析的HTML頁面
另外
Read
trace可以生成RML文件
然後OSTRESS工具使用RML文件多線程地重放Trace文件中的所有事件
這對於那些想把Profiler捕獲的語句在另外一台服務器上重放成為可能
本文不詳細介紹Read
trace或OStress工具
有興趣的讀者請自行參閱相關資料
相關軟件可以從微軟網站下載(注
軟件名稱為RML)
我要利用的是Read
Trace的標准化功能
什麼是標准化?就是把那些語句模式類似
但參數不一樣的語句全部歸類到一起
舉例說Trace中有幾條語句如下
select * from authors where au_lname =
white
select * from authors where au_lname =
green
select * from authors where au_lname =
carson
經過標准化後
上面的語句就變成如下的樣子
select * from authors where au_lname = {str}
select * from authors where au_lname = {str}
select * from authors where au_lname = {str}
有了標准化後的語句
統計出數據庫系統的訪問模式就不再是難事
運行Read
trace 的時候我一般使用如下的命令行
Read
trace –f –dmydb –Imytrace
trc
其中-f開關是不生成RML文件
因為我不需要重放的功能
生成的RML文件比較大
建議讀者如果不需要重放的話
也使用-f開關
-d開關告訴read
trace把trace文件的處理結果存到mydb數據庫中
我們後面創建的存儲過程正是訪問read
trace在mydb中生成的表來進行統計的
-I開關是指定要分析的的trace文件名
Read
trace工具很聰明
如果該目錄下有Profiler產生的一系列Trace文件
如mytrace
trc
mytrace
trc
mytrace
trc等
那麼它會一一順序讀取進行處理
除了上面介紹的外
Read
trace還有很多其它有趣的開關
比如說使用-i開關使得Read
trace可以從zip或CAB文件中讀取trace文件
不用自己解壓
所有開關在Read
trace
chm中有詳細介紹
我最欣賞的地方是read
trace的性能
分析幾個GB大小的trace文件不足一小時就搞定了
我的計算機是一台內存僅為
MB的老機器
有這樣的性能我很滿意
你也許會使用read
trace分析壓力測試產生的trace文件
我建議還是分析從生產環境中捕獲的Trace文件為好
因為很多壓力測試工具都不能夠真正模擬現實的環境
其得到的trace文件也就不能真實反映實際的情況
甚至有些壓力測試工具是循環執行自己寫的語句
更不能反映准確的訪問模式
建議僅僅把壓力測試產生的trace作為參考使用
使用存儲過程分析Normalize後的數據
有了標准化後的語句就可以使用存儲過程進行統計分析了
分析的基本思想是把所有模式一樣的語句的Reads
CPU和Duration做group by統計
得出訪問模式信息
某類語句的總共執行次數
平均讀頁面數(reads)/平均CPU時間/平均執行時間等
該類語句在所有語句的比例
如執行次數比例
reads比例
CPU比例等
存儲過程的定義以及說明如下
Create procedure usp_GetAccessPattern
@duration_filter int=
傳入的參數
可以按照語句執行的時間過濾統計
as begin
/*首先得到全部語句的性能數據的總和*/
declare @sum_total float
@sum_cpu float
@sum_reads float
@sum_duration float
@sum_writes float
select @sum_total=count(*)*
這是所有語句的總數
@sum_cpu=sum(cpu)*
這是所有語句耗費的CPU時間
@sum_reads=sum(reads)*
這是所有語句耗費的Reads數目
K為單位
@sum_writes=sum(writes)*
這是所有語句耗費的Writes數目
K為單位
@sum_duration=sum(duration)*
這是所有語句的執行時間總和
from tblBatches
這是Read
Trace產生的表
包括了Trace文件中所有的語句
where duration>=@duration_filter
是否按照執行時間過濾
/*然後進行Group by
得到某類語句占用的比例*/
Select ltrim(str(count(*))) exec_stats
+ str(count(*)/@sum_total
)+
%
ExecRatio
ltrim(str(sum(cpu)))+
:
++ltrim(str(avg(cpu))) cpu_stats
+str(sum(cpu)/@sum_cpu
)+
%
CpuRatio
ltrim(str(sum(reads) ))+
:
+ltrim(str(avg(reads) )) reads_stats
+str(sum(reads)/@sum_reads
) +
%
ReadsRatio
ltrim(str(sum(writes) ))+
:
+ltrim(str(avg(writes) ))
writes_stats
+str(sum(writes)/@sum_writes
) +
%)
ltrim(str(sum(duration) ))+
:
+ltrim(str(avg(duration))) duration_stats
+str(sum(duration)/@sum_duration
)+
%
DurRatio
textdata
count(*)/@sum_total tp
sum(cpu)/@sum_cpu cp
sum(reads)/@sum_reads rp
sum(duration)/@sum_duration dp
into #queries_staticstics from
/* tblUniqueBatches表中存放了所有標准化的語句
*/
(select reads
cpu
duration
writes
convert(varchar(
)
NormText)textdata from tblBatches
inner join tblUniqueBatches on tblBatches
HashId=tblUniqueBatches
hashid where duration>@duration_filter
) B group by textdata
這個group by很重要
它對語句進行歸類統計
print
Top
order by cpu+reads+duration
select top
* from #queries_staticstics order by cp+rp+dp desc
print
Top
order by cpu
select top
* from #queries_staticstics order by cp desc
print
Top
order by reads
select top
* from #queries_staticstics order by rp desc
print
Top
order by
From:http://tw.wingwit.com/Article/program/SQLServer/201311/22012.html