您的位置:首页 > 数据库

【转载】SQL Server性能调教系列(4)--Profiler(下)

2011-08-21 08:49 281 查看
接上篇:

SQLServer性能调教系列(4)--Profiler(上)



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
H***INGSUM(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,提高效率,大大减少工作量。



原载地址:http://www.cnblogs.com/changbluesky/archive/2010/08/04/1791672.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: