1.首先要有一個trace文件
2. 打開trace文件
3. 另存為跟蹤表
4.登錄你要保存到的目標sqlserver服務器
5. 選擇要保存的數據庫和表名稱
6. 保存完成(左下角出現進度直到顯示“已完成”)
7. 在數據庫中找到該表(在第5步選擇的數據庫中找)
8.查看部分結果(TextData就是查詢的sql語句,Duration就是查詢的時間,這里duration除以1000才是毫秒)
9. 然后我們來分析TextData,如何找到相同的語句,不同的參數。我的分析,TextData主要有3種
1)帶參數sql語句(以 exec sp_executesql N' 打頭,以 ',N' 結尾可以找出對應的sql語句),如下圖
2)存儲過程(類似 exec porc_user_insert @username, exec 和 @ 之間為存儲過程名),如下圖
3)不帶參數的sql語句
10. 對trace表的數據進行處理前的一些准備:
1)update trace_20130910 set duration = duration / 1000 where duration is not null -- 時間改為毫秒
2)修改 textdata 為 nvarchar(max)類型,因為textdata默認保存為ntext類型,處理不方便
alter table trace_20130910 alter column textdata nvarchar(max)
3)新增兩個字段
alter table [trace_20130910] add proc_sql nvarchar(max) -- 保存該textdata調用的存儲過程,原始sql等;
alter table [trace_20130910] add proc_sql_id int -- 為存儲過程和原始sql指定一個編號
11. 處理trace數據
1)找出執行的sql腳本(帶參數) ,更新到 proc_sql 字段
update [trace_20130910]
set proc_sql = replace(left(textdata,charindex(''',N''',textdata) - 1),'exec sp_executesql N''','')
where (proc_sql is null or proc_sql = '' )
and charindex('exec sp_executesql N', textdata ) = 1
2)找出執行的存儲過程,更新到 proc_sql 字段
update [trace_20130910]
set proc_sql =
replace(
replace(
left(
right(textdata,len(textdata) - charindex('exec ',textdata) + 3),
charindex('@',
right(textdata,len(textdata) - charindex('exec ',textdata) + 3)
)
),'exec ','')
,'@','')
where (proc_sql is null or proc_sql = '' )
and charindex('exec ',textdata) > 0
3)找出沒有參數的sql腳本,更新到 proc_sql 字段
update [trace_20130910] set proc_sql = textdata where proc_sql is null and textdata is not null
12. 統計
1)新建表,用於保存統計數據,trace_20130910每個proc_sql對應一行
create table [trace_20130910_stat]
(
id int identity(1,1) primary key,
databaseid int,
proc_sql nvarchar(max), -- 對應trace_20130910的proc_sql
total_duration bigint, -- 總耗時
max_duration int, -- 該語句最大耗時
min_duration int, -- 該語句最小耗時
rate_duration int -- 所耗時間百分比
)
2)生成統計數據,存入1)步的表中 trace_20130910_stat]
;with cte
(
databaseid,
proc_sql,
total_duration,
max_duration ,
min_duration
) as
(
select databaseid,
proc_sql,
sum(duration) as total_duration,
max(duration) as max_duration,
min(duration) as min_duration
from [trace_20130910]
where proc_sql is not null and proc_sql <> ''
group by databaseid,proc_sql
)
, cte2 as
(
-- 總耗時,用來計算百分比
select sum(total_duration) as total_duration from cte
)
insert into [trace_20130910_stat]
(
databaseid,
proc_sql,
total_duration,
max_duration ,
min_duration ,
rate_duration
)
select
databaseid,
proc_sql,
total_duration,
max_duration ,
min_duration ,
100 * total_duration / ( select total_duration from cte2 ) as rate_duration
from cte
order by rate_duration desc
3)更新記錄表[trace_20130910]的 proc_sql_id
update [trace_20130910] set proc_sql_id = b.id
from [trace_20130910] a inner join [trace_20130910_stat] b
on a.databaseid = b.databaseid and a.proc_sql = b.proc_sql
13. 查詢統計結果
1)查出最耗時的語句或過程
select * from [trace_20130910_stat] order by total_duration desc
2)查詢某個過程或者sql語句詳情
select * from [trace_20130910] where proc_sql_id = 1
這是根據duration排序,稍微改下就可以按reads排序,因為步驟畢竟多,而且經常會用到,所以整理成一個存儲過程。方便以后分析性能問題。
找了半天發現不能上傳附件。