测量TSQL语句的性能

你怎样确定你的应用程序执行的怎么样?你可以使用什么工具?每一个开发人员需要确定每一条应用程序TSQL语句是最优的。通过调整每一个查询你可以确定你的应用程序运行得尽可能的高效。你使用开发环境时更容易对应用程序的代码进行修改。一旦你的代码已成为了产品那么要做修改以优化你的代码就可能需要很长的时间,或甚至是不可能的。这就是为什么你需要在应用程序开发过程中定期检查你的应用程序代码的执行情况。本篇文章将讲述关于怎样确定运行较慢的查询的一些不同方法,并提供给你一些小技巧用于在你反复修改每一个查询来试图改进性能的时候监控你的查询性能。

  怎样确定运行较慢的查询

  有了SQL Server 2005你就有了两个不同的选择。第一个选择,就是在其它SQL Server版本中也可用的SQL Server Profiler。而使用SQL Server 2005你就有了“sys.dm_exec_query_stats” DMV。让我们看一下这两个选择怎样用来确定你的运行较慢的查询。

  SQL Server Profiler 是一个易于使用的GUI工具。Profiler 可以用来显示在一个SQL Server 实例上进行的CPU、I/O和SQL Server TSQL 语句的持续时间。为了使Profiler能够用于查找你运行较慢的查询,你需要创建和启动一个profiler跟踪。使用“新跟踪”项可以轻松地做到这一点。Profiler有一个“TSQL持续时间”模版,它可以用来查找你运行时间较长的查询。但是如果你想显示这些运行时间较长的查询所用的CPU和I/O,你将需要创建你自己的Profiler跟踪,或者修改使用“TSQL持续时间”模版所选择的字段。你可以修改“TSQL持续时间”模版:点击“事件选择”标签,然后点击“CPU”,“读”,或“写字段下面的复选框来选择CPU和I/O。要查看更多的关于怎样使用SQL Server Profiler的信息请参考在线书籍。

  如果你有SQL Server 2005,你也可以使用“sys.dm_exec_query_stats” DMV 来确定运行时间较长的查询。这个DMV 可以用来返回缓存查询计划的统计信息。下面是一个关于怎样返回一些针对每一个缓存计划的不同性能测量的示例。

以下是引用片段:
SELECT  creation_time  
        ,last_execution_time 
        ,total_physical_reads
        ,total_logical_reads  
        ,total_logical_writes
        , execution_count 
        , total_worker_time
        , total_elapsed_time 
        , total_elapsed_time / execution_count avg_elapsed_time
        ,SUBSTRING(st.text, (qs.statement_start_offset/2) + 1,
         ((CASE statement_end_offset 
          WHEN -1 THEN DATALENGTH(st.text)
          ELSE qs.statement_end_offset END 
            - qs.statement_start_offset)/2) + 1) AS statement_text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY total_elapsed_time / execution_count DESC;

  我使用这个查询计算了平均实耗时间,然后制定输出,所以具有最差的平均实耗时间的查询显示在第一个。实耗时间是一个用于确定执行较差的查询的较好测量,因为这是处理一个查询所要花费的实际时钟时间。

  通过使用profiler 或DMV查询你可以基于持续时间/实耗时间来确定你的执行很差的查询。一旦你确定了执行较差的查询然后你就可以全力优化这些查询。通过优化较差的查询你将获得最好的性能和以最小代价来改进你的应用程序整个性能。

  帮助优化查询的工具

  当优化查询时你需要在每一次变更之后重复地检查性能信息。进行这项检查使你可以确定你的修改是否起到了改进作用或使你的查询性能更差了。在确定你的查询性能方面有三个有用的测量:实耗时间、I/O和CPU。让我们看看针对一个给定查询测量这三个中每一个的不同方法。

  实耗时间

  一个查询运行所花费的时间叫做实耗时间,也是大家所知道的时钟时间。很多东西会影响查询的实耗时间。实耗时间是测量一个查询执行的怎么样的极好的基准测量,因为它测量了一个用户在SQL server 处理一个特定的查询时要等多久。那么你有哪些不同的方法来测量一个TSQL语句的实耗时间呢?

  你可以使用的第一个方法是当执行一个批处理文件时“实耗时间”会在SQL Server管理套件的查询窗口中显示出来。这是我将等待的时间,如下面的截图所示:

 

  这里我执行了一个循环1亿次添加1。注意我等待的实耗时间是以红色显示在左下角落。如果你在SSMS中运行你的较慢查询,那么你可以使用这个实耗时间显示作为一个对确定你的查询会运行多长时间的一个测量。每一次你改变你的查询和重新运行它,你都可以查看这个时间来确定你的查询是否运行得快些了。

现在另一个测量实耗时间的方法是使用一个SET STATISTICS命令来显示一个查询的实耗时间。下面是一个截屏,它显示了我的查询窗口中执行的每一个语句在查询结果面板中的实耗时间统计信息:

 

  这里我在运行我的简单SELECT语句之前执行了“SET STATISTICS TIME ON”语句。注意“实耗时间”统计在结果面板中显示出来,还有“CPU时间”,以及我的PRINT 语句的输出。“SET STASTISTICS TIME ON”语句显示了解析、编译和执行每一条语句所花费的时间。如果你只执行少量的语句,那么这个语句是很有用的。如果你执行大量的语句,类似于我的第一个循环示例,那么输出的行数将是非常多的,以致难以阅读。

  现在你有时需要测量在一个批处理文件中执行不同的大块代码所花费的时间,而不只是一个指定的TSQL 语句。如果你有一个运行时间很长的大型脚本或存储过程,并且你想找出哪一部分运行时间最长,那么这会是很有用的。要为代码段创建实耗时间,我们可以使用下面的方法:

 

  在这你可以看到我运行了两个不同的简单循环。对于每一个循环,我计算进行这个循环所花费的时间。我将每一个代码块的起始时间放到一个叫做@START的变量里。然后当循环结束时我打印出@START DATETIME 变量和用GETDATE()函数获得的当前时间之间的差值。在我的例子里,第一个循环10,000次花费了16 ms ,而第二个循环90,000次花费了110秒。

  CPU时间

  另一个重要的性能测量是你的查询要返回一个结果集所需要的CPU数量。在上一节中,当我使用“SET STATISTICS TIME ON”语句时在一个批处理文件中显示每一条语句的CPU时间。所以这是你可以用来测量一条TSQL语句CPU消耗的第一个方法。但是,你怎么测量多个语句或者是不同代码块的CPU时间呢?

  SQL Server提供了@@CPU_BUSY系统变量,它用来测量CPU消耗。这是在线书籍上对这个变量的定义:返回SQL Server 从最后一次启动到目前的工作时间。结果就在COU时间增量上,或“标记”,并且是所有CPU时间的累积,所以它可能会超出实际的实耗时间。将它乘以@@TIMETICKS来转化为微秒。

下面的方法是你可以使用@@CPU_BUSY变量来测量在我前一个示例中每一个循环执行过程中SQL Server 所使用的CPU量。现在记住既然@@CPU_BUSY 包含从SQL Server 启动以来使用的CPU量,那么它就包括所有用户和系统在服务器上运行的查询所使用的CPU量。因此只有当只有你在这个系统上运行SQL Server命令而没有后台系统执行查询时,这个方法测量的CPU量才准确:

 

  如同你所看到的,我测量了第一个和第二个循环所使用的CPU毫秒时间。只是让你知道我运行了这个查询几次,获得的每次循环执行实际都不同。所以要注意,使用这个方法会受SQL Server上运行的其它东西影响。我想说的是这个方法对于测量实际的CPU使用不总是可靠的,但是如果你有一个具有较少活动的单独系统,那么它仍然是一个测量CPU消耗的方法。

  一个更精确测量CPU使用的方法是使用SQL Server profiler。它包括CPU字段,显示于不同的完成事件。这里有一个例子是关于我怎样使用SQL Server profiler来捕捉上面的循环批处理所使用的CPU量:

 

  这里我使用SQL:BatchCompleted 事件来捕捉CPU。默认情况下,SQL Profiler 以毫秒显示持续时间。使用“工具——选项”对话框,你可以将这个显示改为微秒。注意这个方法只能测量完整的批处理,而不能测量我的批处理中每一个循环的持续时间。

  I/O使用

  像其它的性能测量一样,也有一些方法显示一个TSQL 语句所使用的I/O数量。在SQL Server 中跟踪的有两个不同类型的I/O:逻辑IO和物理IO。逻辑I/O考虑从内存中的缓冲池进行处理的数据,因此叫做逻辑I/O。物理I/O是从SQL Server用来存储数据库的物理磁盘直接访问数据所关联的I/O。物理I/O是更加昂贵的I/O,意思是说它们花费更长的时间来处理。一般情况下I/O是最昂贵的单一操作,它影响一个TSQL语句的整个性能。所以当你调整你的查询时,你要将执行以生成一个结果集的逻辑I/O和物理I/O操作的数目降低到最小。

一个显示某TSQL 语句或语句批处理文件所关联的I/O 数量的方法是使用“SET STATISTICS IO ON”语句打开I/O 统计信息收集过程。当你在连接时执行这条语句,你将输出用于解决你的TSQL 语句的I/O 数目。下面的例子是我使用“SET STASTISTICS IO ON”语句来显示解决一个对AdventureWorks数据库的简单查询所需要的I/O 数目:

 

  在这你可以看到我的SELECT 语句执行2 “logical reads”,和2 “physical reads”。现在当我第二次运行这个语句批处理时我会得到下面的输出:

 

  这里你将注意到第二次我执行我的TSQL SELECT语句时它只要求2 “logical reads”和0 “physical reads”,这是因为保持了这个查询的AdventureWorks 页面已经缓存在了缓冲池中。如果你进行重复测试试图改进你的查询性能,你需要确保你除去了因为你的查询已经存在于缓冲器缓存中而在页面请求时会发生的I/O计数差异。为了消除这个计数问题,你可以在运行每一个测试之前执行“DBCC DROPCLEANBUFFER”命令。这将使你的查询运行时具有一个干净的缓冲池而不必停止和重启SQL server。

  另一个跟踪查询I/O的方法是使用SQL Server Profiler。要这么做,只要在确定你的跟踪所要监控的事件和字段时确保你包含了I/O相关的字段。

  总结

  能够跟踪你不同查询的资源消耗情况是监控你的应用程序的一个关键之处。知道什么TSQL语句在使用最多的资源可以帮助你确定在优化你的应用程序时要关注什么。“sys.dm_exec_query_stats” DMV 帮助数据库管理员快速确定这些使用最多资源的TSQL语句。使用各种“SET”语句、系统变量和/或SQL Server Profiler 事件/字段可以帮助你测量你的问题TSQL语句的CPU、I/O和消耗时间。确定、测量和改进你的应用程序查询性能将帮助你优化你应用程序背后的代码。

文章出处:http://database.ctocio.com.cn/tips/159/7771659.shtml

猜你喜欢

转载自www.cnblogs.com/binghou/p/9096510.html