sql性能调试-讲解set statistics io 和 set statistics time (转)

本文介绍了如何使用SETSTATISTICSIO和SETSTATISTICSTIME命令来评估SQL查询的性能,重点关注逻辑读取次数和CPU时间,以帮助优化查询效率。

来自:http://www.cnblogs.com/kevinlzf/archive/2009/11/27/1612223.html

距上两篇设计高效sql一般经验谈如何创建效率高sql-建立索引 后,一直想写关于set statistic io 和set statistics time命令的入门介绍,在网上看到这篇不错,偷懒将其转载,希望对那些sql调优入门者有个感性的认识。好了,请看文章。

一个查询需要的CPU、IO资源越多,查询运行的速度就越慢,因此,描述查询性能调节任务的另一种方式是,应该以一种使用更少的CPU、IO资源的方式重写查询命令,如果能够以这样一种方式完成查询,查询的性能就会有所提高。
    如果调节查询性能的目的是让它使用尽可能少的服务器资源,而不是查询运行的时间最短,那么就更容易测试你采取的措施是提高了查询的性能还是降低了查询的性能。尤其是在资源利用不断变化的服务器上更是如此。首先,需要搞清楚在对查询进行调节时,如何测试我们的服务器的资源使用情况。
    在开始我们的例子前,先运行下面的这二条命令(不要在正在使用的服务器上执行),这二条命令将清除SQL Server的数据和过程缓冲区,这样能够使我们在每次执行查询时在同一个起点上,否则,每次执行查询得到的结果就不具有可比性了:DBCC DROPCLEANBUFFERS和DBCC FREEPROCCACHE
输入并运行下面的Transact-SQL命令:
SET STATISTICS IO ON 
SET STATISTICS TIME ON

一旦上面的准备工作完成后,运行下面的查询:
SELECT * FROM [order details]

显示结果:
SQL Server parse and compile time: (SQL Server解析和编译时间:)
CPU time = 10 ms, elapsed time = 61 ms. ……(1)

SQL Server parse and compile time: (SQL Server解析和编译时间:)
CPU time = 0 ms, elapsed time = 0 ms. ……(2)

(所影响的行数为 2155 行) ……(3)

Table 'Order Details'. Scan count 1, logical reads 10, physical reads 1, read-ahead reads 9.
(表:Order Details,扫描次数 1,逻辑读 10,物理读 1,提前读取 9) ……(4)

SQL Server Execution Times:
(SQL Server执行时间:)
CPU time = 30 ms, elapsed time = 387 ms. ……(5)

标志(1)表示SQL Server解析“ELECT * FROM [order details]”命令并将解析的结果放到SQL Server的过程缓冲区中供SQL Server使用所需要的CPU运行时间和总的时间。
标志(2)表示SQL Server从过程缓冲区中取出解析结果供执行的时间,大多数情况下这二个值都会是0,因为这个过程执行得相当地快
标志(5)表示执行这次查询使用了多少CPU运行时间和运行查询使用了多少时间。CPU运行时间是对运行查询所需要的CPU资源的一种相对稳定的测量方法,与CPU的忙闲程度没有关系。但是,每次运行查询时这一数字也会有所不同,只是变化的范围没有总时间变化大。总时间是对查询执行所需要的时间(不计算阻塞或读数据的时间),由于服务器上的负载是在不断变化的,因此这一数据的变化范围有时会相当地大。(由于CPU占用时间是相对稳定的,因此可以使用这一数据作为衡量你的调节措施是提高了查询性能还是降低了查询的性能的一种方法。)
标志(4)是SET STATISTICS IO的效果

 

Scan Count:在查询中涉及到的表被访问的次数。在我们的例子中,其中的表只被访问了1次,由于查询中不包括连接命令,这一信息并不是十分有用,但如果查询中包含有一个或多个连接,则这一信息是十分有用的。(一 个循环外部的表的Scan Count值为1,但对于一个循环内的表而言,其值为循环的次数。可以想象得到,对于一个循环内的表而言,其Scan Count值越小,它所使用的资源越少,查询的性能也就越高。因此在调节一个带连接的查询的性能时,需要关注Scan Count的值,在进行调节时,注意观察它是增加还是减少了。)
Logical Reads: 这是SET STATISTICS IO或SET STATISTICS TIME命令提供的最有用的 数据。我们知道,SQL Server在可以对任何数据进行操作前,必须首先把数据读取到其数据缓冲区中。此外,我们也知道SQL Server何时会从数据缓冲区中读取数据,并把数据读取到大小为8K字节的页中。那么Logical Reads的意义是什么呢?Logical Reads是指SQL Server为得到查询中的结果而必须从数据缓冲区读取的页数。在执行查询时,SQL Server不会读取比实际需求多或少的数据,因此,当在相同的数据集上执行同一个查询,得到的Logical Reads的数字总是相同的。(SQL Server执行查询时的Logical Reads值每一次这个数值是不会变化的。因此,在进行查询性能的调节时,这是一个可以用来衡量你的调节措施是否成功的一个很好的标准。如果 Logical Reads值下降,就表明查询使用的服务器资源减少,查询的性能有所提高。如果Logical Reads值增加,则表示调节措施降低了查询的性能。在其他条件不变的情况下,一个查询使用的逻辑读越少,其效率就越高,查询的速度就越快。)
Physical Reads:物 理读,在执行真正的查询操作前,SQL Server必须从磁盘上向数据缓冲区中读取它所需要的数据。在SQL Server开始执行查询前,它要作的第一件事就是检查它所需要的数据是否在数据缓冲区中,如果在,就从中读取,如果不在,SQL Server必须首先将它需要的数据从磁盘上读到数据缓冲区中。我们可以想象得到,SQL Server在执行物理读时比执行逻辑读需要更多的服务器资源。因此,在理想情况下,我们应当尽量避免物理读操作。下面的这一部分听起来让人容易感到糊涂 了。在对查询的性能进行调节时,可以忽略物理读而只专注于逻辑读。你一定会纳闷儿,刚才不是还说物理读比逻辑读需要更多的服务器资源吗?情况确实是这样, SQL Server在执行查询时所需要的物理读次数不可能通过性能调节而减少的。减少物理读的次数是DBA的一项重要工作,但它涉及到整个服务器性能的调节,而 不仅仅是查询性能的调节。在进行查询性能调节时,我们不能控制数据缓冲区的大小或服务器的忙碌程度以及完成查询所需要的数据是在数据缓冲区中还是在磁盘 上,唯一我们能够控制的数据是得到查询结果所需要执行的逻辑读的次数。

因此,在查询性能的调节中,我们可以心安理得地不理会SET STATISTICS IO命令提供的Physical Read的值。(减少物理读次数、加快SQL Server运行速度的一种方式是确保服务器的物理内存足够多。)
Read-Ahead Reads: 与Physical Reads一样,这个值在查询性能调节中也没有什么用。Read-Ahead Reads表示SQL Server在执行预读机制时读取的物理页。为了优化其性能,SQL Server在认为它需要数据之前预先读取一部分数据,根据SQL Server对数据需求预测的准确程度,预读的数据页可能有用,也可能没用。

在本例中,Read-Ahead Reads的值为9,Physical Read的值为1,而Logical Reads的值为10,它们之间存在着简单的相加关系。那么我在服务器上执行查询时的过程是怎么样的呢?首先,SQL Server会开始检查完成查询所需要的数据是否在数据缓冲区中,它会很快地发现这些数据不在数据缓冲区中,并启动预读机制将它所需要的10个数据页中的 前9个读取到数据缓冲区。当SQL Server检查是否所需要的全部数据都已经在数据缓冲区时,会发现已经有9个数据页在数据缓冲区中,还有一个不在,它就会立即再次读取磁盘,将所需要的 页读到数据缓冲区。一旦所有的数据都在数据缓冲区后,SQL Server就可以处理查询了。

 

总结:在对查询的性能进行调节时用一些科学的标准来测量你的调节措施是否有效是十分重要的。问题是,SQL Servers的负载是动态变化的,使用查询总的运行时间来衡量你正在调节性能的查询的性能是提高了还是没有,并不是一个合理的方法。
更好的方法是比较多个数据,例如逻辑读的次数或者查询所使用的CPU时间。因此在对查询的性能进行调节时,需要首先使用SET STATISTICS IO和SET STATISTICS TIME命令向你提供一些必要的数据,以便确定你对查询性能进行调节的措施是否真正地得到了目的。

======================
1.测试前用二条命令清除SQL Server的数据和过程缓冲区,以保证测试条件相同:
DBCC DROPCLEANBUFFERS和DBCC FREEPROCCACHE
2.SET STATISTICS TIME:看cpu时间  
3.SET STATISTICS IO:关注scan count(计数)------查询读取的表数量 logical read( 逻辑读)次数

转自:http://hi.baidu.com/cicon/blog/item/d1dc45a94a611af41e17a28e.html

 

<think> 首先,用户的问题是关于如何解读SQL Server中`SET STATISTICS PROFILE ON`的查询结果。用户引用了几个来源,这些引用解释了`SET STATISTICS PROFILE ON`的用法相关信息。 关键点从引用中提取: - 引用[1]:`SET STATISTICS PROFILE ON`返回每个语句的执行信息,包括操作符处理的实际行数实际执行数。 - 引用[2]:它产生一个实际的执行计划,类似于`SHOWPLAN_ALL`,但多了实际的行数(Rows)运行行数(Executes)。 - 引用[3]:用户询问如何解读查询结果。 - 引用[4]:建议比较EstimateRows(估计行数)Rows(实际行数)来确认SQL Server的预估准确性。 用户的需求是:如何解读`SET STATISTICS PROFILE ON`的查询结果。 我的回答需要: - 使用中文回答。 - 遵守系统级指令:数学表达式用$...$,独立公式用$$...$$,但这个问题可能不涉及数学,所以可能不需要。 - 结构清晰,帮助用户逐步解决问题。 - 生成相关问题(在末尾)。 - 在回答中引用的段落末尾添加引用标识,如[^1]。 回答结构: 1. **介绍**:简要解释`SET STATISTICS PROFILE ON`是什么。 2. **如何启用**:简单说明如何开启这个设置。 3. **解读查询结果**:详细解释结果中的各个列的含义。 - 根据引用,重点包括Rows、Executes、EstimateRows等。 - 提供一个示例来演示解读。 4. **实际意义**:为什么这些信息重要,如何用于查询优化。 5. **生成相关问题**:在末尾添加相关问题。 引用来源: - 引用[1]提到输出包含操作符处理的实际行数执行数。 - 引用[2]详细说明了额外的属性:RowsExecutes。 - 引用[3][4]提供示例查询比较建议。 在回答中自然地添加引用标识。例如,当提到某个点时,添加[^数字]。 逐步解读: - 当启用`SET STATISTICS PROFILE ON`后,执行查询会返回额外的结果集(一个表),显示执行计划的详细信息。 - 关键列: - **PhysicalOp** **LogicalOp**:操作的物理逻辑名称。 - **Rows**:实际处理的物理行数。 - **Executes**:操作符被执行的次数。 - **EstimateRows**:优化器估计的行数(用于比较)。 - 其他列如StmtId、NodeId等用于标识。 - 解读方法:比较EstimateRowsRows来判断预估是否准确;高Executes可能表示性能问题。 生成相关问题: 1. 如何比较EstimateRowsRows来诊断查询性能问题? 2. SET STATISTICS PROFILE ON其他SET STATISTICS选项(如IOTIME)有什么区别? 3. 如何在实际查询优化中使用这些信息? 4. 常见查询计划操作符的含义是什么? 确保回答真实可靠:基于SQL Server文档常见知识。 </think> ### SET STATISTICS PROFILE ON查询结果的解读方法 `SET STATISTICS PROFILE ON`是SQL Server中的一个诊断命令,用于获取查询的实际执行计划信息。启用后,执行查询会返回两个结果集:常规查询结果一个额外的“执行配置文件”表。后者详细描述了查询的执行过程,包括操作符的实际处理行数、执行次数等关键指标,这对查询性能分析优化至关重要[^1][^2]。下面我将逐步解释如何解读其查询结果。 #### 1. **开启SET STATISTICS PROFILE ON** 在执行查询前,运行以下命令启用该功能: ```sql SET STATISTICS PROFILE ON; GO -- 示例查询 SELECT DISTINCT ProductID, UnitPrice FROM SalesOrderDetail WHERE ProductID = 777; GO ``` 执行后,查询结果下方会附加一个表格形式的输出。该表格包含多列,我们需要重点关注几个核心列来解读执行计划。 #### 2. **关键列的含义及解读方法** 执行配置文件输出是一个表格,每行代表查询计划中的一个操作符(如索引扫描、键查找等)。以下是主要列的解释如何解读: - **Rows**: 操作符**实际处理的物理行数**。这是最关键的指标之一,表示该步骤处理了多少行数据。例如,如果`Rows`值很高,可能表示该操作(如扫描)效率低下,需要优化索引[^2][^4]。 - *解读示例*:在`WHERE ProductID = 777`的查询中,如果`Rows`显示为500,说明该条件实际筛选了500行数据。 - **Executes**: 操作符**实际被执行的次数**。如果该值大于1,可能表示冗余操作或循环执行,常见于嵌套查询或JOIN操作中[^1][^2]。 - *解读示例*:在JOIN查询中,如果`Executes`为10,表示内表被扫描了10次,这可能导致性能瓶颈。 - **EstimateRows**: 优化器**预估的处理行数**(基于统计信息)。通过`Rows`比较,可以判断优化器的预估是否准确。如果`EstimateRows``Rows`差异大(如预估100行,实际1000行),说明统计信息过时或查询条件选择性差,需要更新统计信息或优化查询[^4]。 - *解读示例*:引用[4]中的示例显示,比较`EstimateRows``Rows`是诊断预估错误的常用方法。 - **PhysicalOp** **LogicalOp**: 分别表示**物理操作符**(如Index Scan、Hash Match)**逻辑操作符**(如Inner Join、Aggregate)。这些列描述操作的类型。逻辑操作符表示优化器的意图,物理操作符表示实际执行方式。 - *解读示例*:`PhysicalOp`显示为"Index Scan"表示使用了索引扫描,而"Index Seek"更高效;如果显示"Table Scan",表示全表扫描,通常需要添加索引。 - **Argument**: 操作符的**详细信息**,如使用的索引名或过滤条件。这有助于识别具体执行对象。 - *解读示例*:`Argument`显示为`[PK_SalesOrderDetail]`时,表示操作基于主键索引。 - **NodeId** **Parent**: 表示操作符在**执行计划树中的位置层级**。`NodeId`是当前节点ID,`Parent`是其父节点ID(根节点Parent为0)。这用于理解操作符的依赖关系。 - *解读示例*:一个有`Parent`为1的节点,表示它是ID=1的节点的子操作(如JOIN的子查询)。 #### 3. **解读步骤示例** 假设执行配置文件输出如下片段(简化示例): | NodeId | Parent | LogicalOp | PhysicalOp | EstimateRows | Rows | Executes | Argument | |--------|--------|---------------|---------------|--------------|------|----------|-------------------| | 1 | 0 | Inner Join | Hash Match | 1000 | 1200 | 1 | NULL | | 2 | 1 | Index Scan | Index Scan | 500 | 600 | 1 | [IX_ProductID] | | 3 | 1 | Key Lookup | Key Lookup | 500 | 600 | 1 | [PK_SalesOrder] | - **整体解读**:这是一个JOIN查询(NodeId 1),实际处理1200行(高于预估的1000行),执行一次。其子操作包括索引扫描(NodeId 2)键查找(NodeId 3),各处理600行。 - **关键分析**: - `EstimateRows` (1000) `Rows` (1200) 差异较大,表示统计信息可能需要更新[^4]。 - 所有`PhysicalOp`显示高效操作(Hash Match、Index Scan),但如果`PhysicalOp`出现"Table Scan",则需优化索引。 - `Executes`均为1,表示无冗余执行。 #### 4. **实际应用优化意义** - **性能诊断**:比较`Rows``EstimateRows`可以识别预估错误,这是查询变慢的常见原因(如引用[4]所述)。高`Rows`或高`Executes`的操作符通常是优化重点。 - **优化建议**: - 如果`Rows`显著大于`EstimateRows`,运行`UPDATE STATISTICS`更新统计信息。 - 如果`PhysicalOp`包含扫描操作,考虑添加缺失索引。 - 高`Executes`可能提示重构查询,避免嵌套循环[^2][^3]。 - **其他命令对比**:`SET STATISTICS PROFILE ON`提供实际数据(实际行数),而`SET SHOWPLAN_ALL ON`只显示预估计划,不包含实际执行细节[^2]。结合`SET STATISTICS IO ON`(查看I/O开销)`SET STATISTICS TIME ON`(查看编译/执行时间)能全面分析性能[^2]。 通过以上解读,您可以快速定位查询瓶颈。例如,引用[3]中的示例通过`SET STATISTICS PROFILE ON`分析了`WHERE`条件的实际影响,帮助优化筛选逻辑。 ### 相关问题 1. 如何结合SET STATISTICS PROFILE ONSET STATISTICS IO ON进行全面的查询性能分析? 2. 当EstimateRowsRows差异较大时,有哪些具体方法来更新统计信息或优化查询? 3. SET STATISTICS PROFILE ON在诊断嵌套查询或存储过程时的特殊应用场景是什么? 4. 常见的执行计划操作符(如Hash Match、Index Seek)如何影响查询效率,如何优化它们?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值