SQL Server性能调教系列(4)--Profiler(下)
2010-08-04 08:16
267 查看
接上篇:
SQLServer性能调教系列(4)--Profiler(上)
3.分析跟踪记录
在跟踪了一段时间之后,在文件中就会保存有跟踪的数据(包括IO,Duration,CPU,Reads,Writes,RowCounts等计数器),接下来就是把跟踪的数据加载到表并分析这些数据。可以选择在Profile中打开并检查这些跟踪数据,会有些限制,如不能完成太多的操作,大量重复的SQL语句,没有汇总。
3.1加载数据到表(使用函数fn_trace_gettable返回表格形式的数据,作为范例只选择分析T-SQL代码和Duration查询的运行时间)
3.2汇总相同的SQL项
问题:分组聚合后会看到逻辑上相同(参数不同)的查询会被分到不同的组,因为在筛选器中使用了不同的值。因为这些相同逻辑的SQL会使用相同的执行计划,应该聚合在一起才能准备的分析总的查询运行的时间。
3.3问题处理方案一(大致分段截取)
通常情况下SQL语句都是Select+栏位,左边有很大一部分是相同的,根据SQL字符的长度,截取前一段来聚合。如取前50,100,150.方法简单,容易操作,会聚合一部分数据,但是长度不太好取值,只能调整前缀的长度去测试。
3.4问题处理方案二(复杂,精确,逻辑上相同的SQL,参数用通配符替代),这个方法是T-SQL查询技术内幕中介绍的方法,如果需要更加详细的说明,请阅读这本书,你会得到更多的启发。
(1)模式化查询,它对于相同模式的查询是一样的。
T-SQL函数实现
建立函数:
该函数参数为一个查询字符串和要分析的代码的长度,但会输入查询的签名,并用井号(#)替换所有的参数。测试结果如下:
CLR实现
CLR在处理迭代/过程逻辑和字符串处理时比T-SQL效率高,下面介绍用CLR实现模式化查询。
a.建立C#版的ClasssLibary,函数如下:
b.加载.dll中间语言代码到DB
c.注册函数fn_SQLSigCLR和fn_RegexReplace
d.注册完成之后,用下面代码测试:
结果的SQL全被模式化,井号(#)替代所有的参数。
(2)以用上面建立的函数,模式化追踪的T-SQL语句,并分类汇总。
a.以用查询签名,为每个字符串生成整数的校验和(CheckSum),方便以后的汇总计算,提高效率:
b.用每个签名的检验和计算运行时间填充临时表#AggQueries,包括运行时间的百分比,以及运行时间降序的行号。
查询聚合之后临时表的内容,数据量会大大的减少,包含签名,总的运行时间,运行时间占总运行时间的半分比,排序序号。
c.筛选并匹配,使用APPLY运算符得到查询模式和一个示例查询。
4.有了查询模式,示例查询,和占用时间的百分比例和排序。然后就可以着手优化。也可以通过类似的方式,找到造成大量结果集,大多数的I/O问题的查询模式。
四:总结
Perfiler是一个很好用的工具来追踪系统的性能和工作的负荷,从而准确的找到值得优化的SQL,提高效率,大大减少工作量。
附件下载:Server性能计数器.rar
PerformanceMonitor.rar
参考:MicrosoftSQLServer2005技术内幕:T-SQL查询
>>>SQLServer性能调校系列入口地址
3.分析跟踪记录
在跟踪了一段时间之后,在文件中就会保存有跟踪的数据(包括IO,Duration,CPU,Reads,Writes,RowCounts等计数器),接下来就是把跟踪的数据加载到表并分析这些数据。可以选择在Profile中打开并检查这些跟踪数据,会有些限制,如不能完成太多的操作,大量重复的SQL语句,没有汇总。
3.1加载数据到表(使用函数fn_trace_gettable返回表格形式的数据,作为范例只选择分析T-SQL代码和Duration查询的运行时间)
selectCAST(textdataasnvarchar(max))astsql_code,duration intoWorkload fromsys.fn_trace_gettable('C:\test\performancetrace_20100802.trc',NULL)asTT
3.2汇总相同的SQL项
selecttsql_code,SUM(duration)astotal_durationfromworkloadgroupbytsql_code
(由于我是在Production上面做的trace,考虑到系统的安全性,在此不便透露分析的SQL代码,实在很抱歉,各位朋友如有兴趣可在自己的测试环境中测试,讨论测试的结果)
问题:分组聚合后会看到逻辑上相同(参数不同)的查询会被分到不同的组,因为在筛选器中使用了不同的值。因为这些相同逻辑的SQL会使用相同的执行计划,应该聚合在一起才能准备的分析总的查询运行的时间。
3.3问题处理方案一(大致分段截取)
通常情况下SQL语句都是Select+栏位,左边有很大一部分是相同的,根据SQL字符的长度,截取前一段来聚合。如取前50,100,150.方法简单,容易操作,会聚合一部分数据,但是长度不太好取值,只能调整前缀的长度去测试。
selectleft(tsql_code,50)ast_sql,SUM(duration)astotal_durationfromworkloadgroupbyleft(tsql_code,50)
--or
selectleft(tsql_code,100)ast_sql,SUM(duration)astotal_durationfromworkloadgroupbyleft(tsql_code,100)
--or
selectleft(tsql_code,150)ast_sql,SUM(duration)astotal_durationfromworkloadgroupbyleft(tsql_code,150)
3.4问题处理方案二(复杂,精确,逻辑上相同的SQL,参数用通配符替代),这个方法是T-SQL查询技术内幕中介绍的方法,如果需要更加详细的说明,请阅读这本书,你会得到更多的启发。
(1)模式化查询,它对于相同模式的查询是一样的。
T-SQL函数实现
建立函数:
CREATEFUNCTION[dbo].[fn_SQLSigTSQL]
(@p1NTEXT,@parselengthINT=4000)
RETURNSNVARCHAR(4000)
--Thisfunctionwillreplacetheparameterswith'#'
--Thisfunctionisprovided"ASIS"withnowarranties,
--andconfersnorights.
--Useofincludedscriptsamplesaresubjecttothetermsspecifiedat
--http://www.microsoft.com/info/cpyright.htm--
--Stripsquerystrings
AS
BEGIN
DECLARE@posASINT;
DECLARE@modeASCHAR(10);
DECLARE@maxlengthASINT;
DECLARE@p2ASNCHAR(4000);
DECLARE@currcharASCHAR(1),@nextcharASCHAR(1);
DECLARE@p2lenASINT;
SET@maxlength=LEN(RTRIM(SUBSTRING(@p1,1,4000)));
SET@maxlength=CASEWHEN@maxlength>@parselength
THEN@parselengthELSE@maxlengthEND;
SET@pos=1;
SET@p2='';
SET@p2len=0;
SET@currchar='';
set@nextchar='';
SET@mode='command';
WHILE(@pos<=@maxlength)
BEGIN
SET@currchar=SUBSTRING(@p1,@pos,1);
SET@nextchar=SUBSTRING(@p1,@pos+1,1);
IF@mode='command'
BEGIN
SET@p2=LEFT(@p2,@p2len)+@currchar;
SET@p2len=@p2len+1;
IF@currcharIN(',','(','','=','<','>','!')
AND@nextcharBETWEEN'0'AND'9'
BEGIN
SET@mode='number';
SET@p2=LEFT(@p2,@p2len)+'#';
SET@p2len=@p2len+1;
END
IF@currchar=''''
BEGIN
SET@mode='literal';
SET@p2=LEFT(@p2,@p2len)+'#''';
SET@p2len=@p2len+2;
END
END
ELSEIF@mode='number'AND@nextcharIN(',',')','','=','<','>','!')
SET@mode='command';
ELSEIF@mode='literal'AND@currchar=''''
SET@mode='command';
SET@pos=@pos+1;
END
RETURN@p2;
END
该函数参数为一个查询字符串和要分析的代码的长度,但会输入查询的签名,并用井号(#)替换所有的参数。测试结果如下:
selectdbo.fn_SQLSigTSQL('select*fromSales.SalesOrderHeaderwhereSalesOrderID=''43659''andStatus=''5''',500)
CLR实现
CLR在处理迭代/过程逻辑和字符串处理时比T-SQL效率高,下面介绍用CLR实现模式化查询。
a.建立C#版的ClasssLibary,函数如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingMicrosoft.SqlServer.Server;
usingSystem.Data.SqlTypes;
usingSystem.Text.RegularExpressions;
publicpartialclassSQLSignature
{
//fn_SQLSigCLR
[SqlFunction(IsDeterministic=true,DataAccess=DataAccessKind.None)]
publicstaticSqlStringfn_SQLSigCLR(SqlStringquerystring)
{
return(SqlString)Regex.Replace(
querystring.Value,
@"([\s,(=<>!](?![^\]]+[\]]))(?:(?:(?:(?#expressioncoming
)(?:(
)?(')(?:[^']|'')*('))(?#character
)|(?:0x[\da-fA-F]*)(?#binary
)|(?:[-+]?(?:(?:[\d]*\.[\d]*|[\d]+)(?#precisenumber
)(?:[eE]?[\d]*)))(?#imprecisenumber
)|(?:[~]?[-+]?(?:[\d]+))(?#integer
))(?:[\s]?[\+\-\*\/\%\&\|\^][\s]?)?)+(?#operators
))",
@"$1$2$3#$4");
}
//fn_RegexReplace-forgenericuseofRegEx-basedreplace
[SqlFunction(IsDeterministic=true,DataAccess=DataAccessKind.None)]
publicstaticSqlStringfn_RegexReplace(
SqlStringinput,SqlStringpattern,SqlStringreplacement)
{
return(SqlString)Regex.Replace(
input.Value,pattern.Value,replacement.Value);
}
}
b.加载.dll中间语言代码到DB
USEmaster;
CREATEASSEMBLYSQLSignature
FROM'C:\SQLSignature\SQLSignature\bin\Debug\SQLSignature.dll';
c.注册函数fn_SQLSigCLR和fn_RegexReplace
CREATEFUNCTIONdbo.fn_SQLSigCLR(@querystringASNVARCHAR(MAX))
RETURNSNVARCHAR(MAX)
WITHRETURNSNULLONNULLINPUT
EXTERNALNAMESQLSignature.SQLSignature.fn_SQLSigCLR;
GO
CREATEFUNCTIONdbo.fn_RegexReplace(
@inputASNVARCHAR(MAX),
@patternASNVARCHAR(MAX),
@replacementASNVARCHAR(MAX))
RETURNSNVARCHAR(MAX)
WITHRETURNSNULLONNULLINPUT
EXTERNALNAMESQLSignature.SQLSignature.fn_RegexReplace;
GO
d.注册完成之后,用下面代码测试:
SELECT
dbo.fn_SQLSigCLR(tsql_code)ASsig_sql,
duration
FROMdbo.Workload;
结果的SQL全被模式化,井号(#)替代所有的参数。
(2)以用上面建立的函数,模式化追踪的T-SQL语句,并分类汇总。
a.以用查询签名,为每个字符串生成整数的校验和(CheckSum),方便以后的汇总计算,提高效率:
ALTERTABLEdbo.WorkloadADDcsINTNOTNULLDEFAULT(0);
GO
UPDATEdbo.Workload
SETcs=CHECKSUM(dbo.fn_SQLSigCLR(tsql_code));
CREATECLUSTEREDINDEXidx_cl_csONdbo.Workload(cs);
b.用每个签名的检验和计算运行时间填充临时表#AggQueries,包括运行时间的百分比,以及运行时间降序的行号。
IFOBJECT_ID('tempdb..#AggQueries')ISNOTNULL
DROPTABLE#AggQueries;
GO
SELECTcs,SUM(duration)AStotal_duration,
100.*SUM(duration)/SUM(SUM(duration))OVER()ASpct,
ROW_NUMBER()OVER(ORDERBYSUM(duration)DESC)ASrn
INTO#AggQueries
FROMdbo.Workload
GROUPBYcs;
CREATECLUSTEREDINDEXidx_cl_csON#AggQueries(cs);
查询聚合之后临时表的内容,数据量会大大的减少,包含签名,总的运行时间,运行时间占总运行时间的半分比,排序序号。
c.筛选并匹配,使用APPLY运算符得到查询模式和一个示例查询。
WITHRunningTotalsAS
(
SELECTAQ1.cs,
CAST(AQ1.total_duration/1000.
ASDECIMAL(12,2))AStotal_s,
CAST(SUM(AQ2.total_duration)/1000.
ASDECIMAL(12,2))ASrunning_total_s,
CAST(AQ1.pctASDECIMAL(12,2))ASpct,
CAST(SUM(AQ2.pct)ASDECIMAL(12,2))ASrun_pct,
AQ1.rn
FROM#AggQueriesASAQ1
JOIN#AggQueriesASAQ2
ONAQ2.rn<=AQ1.rn
GROUPBYAQ1.cs,AQ1.total_duration,AQ1.pct,AQ1.rn
HAVINGSUM(AQ2.pct)-AQ1.pct<=90--percentagethreshold
)
SELECTRT.rn,RT.pct,S.sig,S.tsql_codeASsample_query
FROMRunningTotalsASRT
CROSSAPPLY
(SELECTTOP(1)tsql_code,dbo.fn_SQLSigCLR(tsql_code)ASsig
FROMdbo.WorkloadASW
WHEREW.cs=RT.cs)ASS
ORDERBYRT.rn;
4.有了查询模式,示例查询,和占用时间的百分比例和排序。然后就可以着手优化。也可以通过类似的方式,找到造成大量结果集,大多数的I/O问题的查询模式。
四:总结
Perfiler是一个很好用的工具来追踪系统的性能和工作的负荷,从而准确的找到值得优化的SQL,提高效率,大大减少工作量。
附件下载:
参考:MicrosoftSQLServer2005技术内幕:T-SQL查询
>>>
相关文章推荐
- SQL Server性能调教系列(4)--Profiler(上)
- SQL Server性能调教系列(4)--Profiler(上)
- SQL Server性能调教系列(4)--Profiler(下)
- 【飞秋】SQL Server性能调教系列(4)--Profiler(上)
- 【转载】SQL Server性能调教系列(4)--Profiler(上)
- 【转载】SQL Server性能调教系列(4)--Profiler(下)
- 《MS SQL Server 2000管理员手册》系列——35. 使用SQL Query Analyzer和SQL Profiler
- 【转载】SQL Server性能调教系列(2)--Server Performance Monitor(Perfmon)
- [屌丝的逆袭系列]进程注入是王道之为NhibernateProfiler增加“附加到进程”功能-原理(源码)
- 【转载】SQL Server性能调教系列(1)-概述
- SQL Server性能调教系列(1)-概述
- Red Gate 系列(.NET Reflector 8|ANTS Performance Profiler|SQL Prompt)产品注册机/源代码
- IOS性能调优系列:使用Time Profiler发现性能瓶颈
- SQL Server性能调教系列(1)-概述
- PLSQL_性能优化工具系列03_DBMS_PROFILER / DBMS_TRACE / DBMS_HPROF(待整理)
- 1.采用MiniProfiler监控EF与.NET MVC项目(Entity Framework 延伸系列1)
- 【脚本语言系列】关于Python代码分析工具line_profiler,你需要知道的事
- SQL Server性能调教系列(5)--SQL Server配置
- [屌丝的逆袭系列]进程注入是王道之为NhibernateProfiler增加“附加到进程”功能-介绍
- SQL Server性能调教系列(6)—Index Structure and Tuning