SQL查询性能的好坏直接影响到整个数据库的价值,对此,必须郑重对待。
SQL Server提供了多种工具,下面做一个简单的介绍:
一、SQL Profiler工具
SQL Profiler可用于:
l 图形化监视SQLServer查询;
l 在后台收集查询信息;
l 分析性能;
l 诊断像死锁这样的问题;
l 调试Transact-SQL(T-SQL)语句;
l 模拟重放SQLServer活动
注意:定义一个跟踪最有效的方法是通过系统存储过程,但是学习的起点还是通过GUI。
1.1、Profiler跟踪:
建议使用标准模版
1.2、事件:
一个事件表现SQLServer中执行的各种活动。可以简单分类为:事件类、游标事件、锁事件、存储过程事件和T-SQL事件。
对于性能分析,主要关心以下部分:
l SQL活动涉及哪一类的CPU使用?
l 使用了多少内存?
l 涉及多少I/O操作?
l SQL活动执行了多长时间?
l 特定的查询执行的频率多高?
l 查询面对哪类错误和警告?
跟踪查询结束的事件:
逻辑读、写由内存中的8KB页面活动组成,可能需要0或者多个物理I/O。找到物理I/O操作数,使用系统监视工具。
二、跟踪的自动化
注意:SQL Profiler对性能存在负面影响,如非必要不要在生产环境长期使用。
1.使用GUI捕捉跟踪:
可以使用两种方法创建脚本化的跟踪——手工或GUI:
可以使用Profiler的导出功能导出脚本。
2.使用存储过程捕捉跟踪:
l Sp_trace_create:创建一个跟踪定义。
l Sp_trace_setevent:添加事件和事件列到跟踪中。
l Sp_trace_setfilter:将过滤器应用到跟踪。
可以使用内建函数:fn_trace_getinfo确定正在运行的跟踪:
SELECT * FROM ::fn_trace_getinfo(default);
可以重新执行fn_trace_getinfo函数确认是否已经关闭。
三、结合跟踪和性能监视器输出
可以结合SQL Profiler和性能监视器来分析性能,此处不多说
四、SQL Profiler建议
使用SQL Profiler时,要考虑以下几点:
l 限制事件和数据列的数量;
l 抛弃用于性能分析的启动事件;
l 限制跟踪输出大小;
l 避免联机数据列排序;
l 远程运行Profiler
1、 限制事件和数据列:
捕捉像锁和执行计划这样的事件时应该小心进行,因为输出会变得非常大并降低SQL Server性能。
2、 丢弃性能分析所用的启动事件:
像SP:StmtStarting这样的启动事件不提供分析信息,因为只有事件完成才能计算I/O量、CPU负载和查询的持续时间。
使用捕捉启动事件的时机是:预期某些SQL查询因为错误而不能结束执行,或者频繁发现Attention事件按的时候捕捉。因为Attention事件一般表示用户中途撤销了查询或者查询超时,可能因为查询运行了太长时间。
3、 限制跟踪输出大小:
在Edit Filter(编辑过滤器)对话框中做以下设置:
l Duration-Greater than or equal:2(持续事件>=2):持续事件等于0或1ms的查询不能进一步优化。
l Reads-Greater than or equal:2(读操作数量>=2):逻辑读数量等于0或1的查询不能进一步优化。
4、 避免在线数据列排序:
(1)、捕捉跟踪,不做任何排序或分组。
(2)、保存跟踪输出到一个跟踪文件。
(3)、打开跟踪文件并按照需要排序。
5、 远程运行Profiler:
使用系统存储过程比使用GUI对性能方面有好处。
6、 限制使用某些事件:在已经遇到压力的系统上,不要使用Showplan XML事件
五、没有Profiler情况下的查询性能度量
对于需要立即捕捉系统,使用DMV:sys.dm_exec_query_stats比Profiler有效,如果需要查询运行机器单独开销的历史记录,跟踪仍是更好的工具。
sys.dm_exec_query_stats:获取服务器上查询计划统计的信息:
列
描述
Plan_handle
引用执行计划的指针
Creation_time
计划创建的时间
Last_execution time
查询最后一次使用计划的时间
Execution_count
计划已经使用的次数
Total_worker_time
从创建起计划使用的CPU时间
Total_logical_reads
从创建起计划使用的读操作数量
Total_logical_writes
从创建起计划使用的写操作数量
Query_hash
可用于识别有类似逻辑的查询的一个二进制hash
Query_plan_hash
可用于识别有相似逻辑的计划的一个二进制hash
为了过滤信息,需要关联其他DMF。如sys.dm_exec_sql_text来查看查询文本。
Sys.dm_query_plan显示查询的执行计划。从而限制不必要的返回信息。
六、开销较大的查询
对于收集结果,应该分析两部分:
l 导致大量系统资源压力的查询;
l 速度降低最严重的查询
1、 识别开销较大的查询:
对于返回的跟踪数据,CPU和Reads列显示了查询开销所在。在执行读操作时,内存页面必须在操作查询中被备份,在第一次数据访问期间写入,并在内存瓶颈时被移到磁盘。过多页面CPU还会增加管理页面的负担。
导致大量逻辑读的查询通常在相应的大数据集上得到锁。即使读,也需要在所有数据上的共享锁。阻塞了其他请求修改的查询。但不阻塞读数据的查询。如果查询很久,那么会持续阻塞其他查询,被阻塞的查询进一步阻塞其他查询,引起数据中的阻塞链。
结论,识别开销大的查询并首先优化它们从而达到以下效果:
l 增进开销较大的查询本身的性能;
l 降低系统资源上的总体压力;
l 减少数据库阻塞;
开销大的查询有两类:
l 单次执行:查询一次开销较大
l 多次执行:查询本身不大,但是重复执行导致系统资源上的压力。
1.单次执行开销较大的查询:
可以使用SQL Profiler,或者查询sys.dm_exec_query_stats来识别开销大的查询。
(1)、捕捉表示典型工作负载的Profiler跟踪。
(2)、将跟踪输出保存到一个跟踪文件。
(3)、打开跟踪文件进行分析。
(4)、打开跟踪的Properties(属性)窗口,单击Event Selection(事件选择)选项卡。
(5)、单机按钮打开Organize Columns(组织列)窗口。
(6)、在Reads列上分组跟踪输出。
(7)、使用分组的跟踪。
2.多次执行开销较大的查询:
l 这种情况下,Profiler中跟踪输出的以下列上分组:EventClass、TextData和Reads。
l 导出Profiler跟踪表。使用内建函数fn_trace_gettable导入到一个跟踪表。
l 访问sys.dm_exec_query_statsDMV从生产服务器检索信息。
把数据装入到数据库的一个表中
SELECT *INTO Trace_TableFROM ::FN_TRACE_GETTABLE('C:\PerformanceTrace.trc', DEFAULT)
执行下面语句查询多次执行的读操作总数:
SELECT COUNT(*) AS TotalExecutions ,EventClass ,TextData ,SUM(Duration) AS Duration_Total ,SUM(CPU) AS CPU_Total ,SUM(Reads) AS Reads_Total ,SUM(Writes) AS Writes_TotalFROM Trace_TableGROUP BY EventClass ,TextDataORDER BY Reads_Total DESC
SQL Server 2008不支持在NTEXT数据类型进行分组。而TextData是ntext类型,要转换成Nvarchar(max)
3.识别运行缓慢的查询:
需要定期监视输入的SQL查询的执行时间,并找出运行缓慢的查询的响应时间。但是不是所有运行缓慢的查询都是由于资源问题形成。如阻塞那些都有可能导致缓慢的查询。
可以在Duration上跟踪。
七、执行计划
1、 分析查询计划
执行计划从右到左,从上到下的顺序阅读。每个步骤代表获得查询最终输出所执行的操作。执行计划有以下特征:
l 如果查询由多个查询的批组成,每个查询的执行计划按照执行的顺序显示。批中的每个执行将有一个相对的估算开销,整个批的总开销为100%。
l 执行计划中的每个图标代表一个操作符。有相对的估算开销,所有节点的总开销为100%。
l 执行计划中的一个起始操作符通常表示一个数据库对象(表或索引)的数据检索机制。
l 数据检索通常是一个表操作或索引操作。
l 索引上的数据检索将是索引扫描或索引查找。
l 索引上的数据检索的命名惯例是[表名].[索引名]。
l 数据从右到左在两个操作之间流动,由一个连接箭头表示。
l 操作符之间连接箭头的宽度是传输行数的图形表示。
l 同一列的两个操作符之间的连接机制将是嵌套的循环连接,hash匹配连接或者合并连接。
l 将光标放置在执行计划的一个节点上,显示一个具有一些细节的弹出窗口。
l 在Properties(属性)窗口中有完整的一组关于操作符的细节。可以右键单击操作符并选择Properties。
l 操作符细节在顶部显示物理和逻辑操作的类型。物理操作代表存储引擎实际使用的,而逻辑操作是优化器用于建立估算执行计划的结构。如果相同,只显示物理操作。还会显示其他信息:I/O、CPU等。
l 操作符细节弹出窗口的Argument(参数)部分在分析中特别有用,因为显示了优化器锁使用的过滤或连接条件。
2、 识别执行计划中开销较大的步骤:
l 执行计划中每个节点显示整个计划中的相对开销,整个计划总开销为100%。关注最高相对开销的节点。
l 执行计划可能来自于一批语句,因此可能也需要查找开销最大的语句。
l 查看节点之间连接箭头的宽度。非常宽的连接箭头表示对应节点之间的传输大量的行。分析箭头左边的节点以理解需要这么多行的原因,还要检查箭头的属性。可能看到估计的行和实际的行不一样,这可能由过时的统计造成。
l 寻找hash连接操作。对于小的数据集,嵌套的循环连接通常是首选的连接技术。
l 寻找书签查找操作。对于大结果集的书签操作可能造成大量的逻辑读。
l 如果操作符上有一个叹号的警告,是需要立刻注意的领域。这些警告可能是由各种问题造成的,包括没有连接条件的连接或者丢失统计的索引和表。
l 需找执行排序操作的步骤,这表示数据没有以正确的排序进行检索。
3、 分析索引有效性:
要关注【扫描】,扫描代表访问大量的行。可以通过以下方式判断索引有效性:
l 数据检索操作
l 连接操作
有时候执行计划中没有【断言】(predicate),缺乏断言意味着整个表(聚簇索引就是该表)被作为合并连接操作符的输入进行扫描。
4、 分析连接有效性:
SQLServer使用3中连接类型:
l Hash连接;
l 合并连接
l 嵌套循环连接
1、 Hash连接:
1.1、Hash连接高效处理大的、未排序的、没有索引的输入。
1.2、Hash连接使用两个连接输入:建立输入(build input)和探查输入(probe input)。建立输入是执行计划中上面的那个输入,探查输入是下面那个输入。
1.3、最常见的hash连接方式——in-memory hash join,整个建立输入被扫描或计算然后在内存中建立一个hash表。每个行根据计算的hash键值(相等断言中的一组列)被插入一个hash表元中。
内存hash连接的示意图: