理解图形化执行计划 -- 第1部分:讲解执行计划

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:

英文原文:

http://www.sqlservercentral.com/articles/Execution+Plan/105771/


对于SQL Server数据库管理员和开发来说,能够理解和分析执行计划是一项非常重要且有益的技能。执行计划将查询的预估花销、索引使用和执行的操作文档化输出。所有的信息对于试着加速一个慢查询来说都是极其重要的。


这篇文章是关于图形化执行计划的三部分系列文章之一。第1部分解释了执行计划是什么,并讨论了预估和实际执行计划的不同。第2部分显示了如何创建预估和实际执行计划。最后,第3部分深入一个简单的图形化执行计划,并讨论了一些最普遍的查询中的操作。


什么是执行计划?


查询优化器是SQL Server的一个组件,用于分析查询的信息和相关表、索引和索引视图的可用统计信息。统计信息允许查询比较表中大量的行与索引中的唯一值,来决定哪个索引会降低查询的消耗。


查询优化器使用统计信息来创建一些不同的执行计划。每个执行计划是一步步的操作文档和这些操作的顺序,可用于返回查询结果的一种方式被执行。不同的执行计划会尝试使用不同的索引,查找或扫描(更多关于查找和扫描的在第3部分),不同类型的连接(查看第3部分更多关于连接),和以不同顺序的操作找到最佳执行计划。


接下来,优化器针对每个操作分配相对消耗的I/O和处理器。然后对于每个执行计划的每个操作的消耗求和来生成总的消耗。在完成一些不同的执行计划后,它然后选择最低消耗的执行计划,并且使用该计划执行查询。重要的是记住这些消耗是优化器计算的相对值,并且不能与任何完成执行的真实值比较(例如CPU和I/O时间)。


一旦执行计划被优化器选择,它会被存储在缓存中。下一次查询被执行,优化器会查找缓存看是否对这个查询包含有执行计划。如果执行计划被找到,它将被用于执行这个查询,节省了创建新的预估执行计划的时间。


非图形化执行计划


除了图形化执行计划,也有纯文本和XML格式执行计划。纯文本执行计划是微软可用的第一种执行计划,并且难以阅读。伴随着XML格式执行计划的出现,微软将会在将来版本的SQL Server中废弃纯文本执行计划。XML执行计划的关键价值是它们可以被保存并之后以图形化执行计划打开。以XML格式保存执行计划,查看导出执行计划或者TechNet文章“以XML格式保存执行计划”。关于纯文本和XML执行计划的更多信息,查看Grant Fritchey的书SQL Server执行计划


预估执行计划 VS 实际执行计划


有两种类型的执行计划:预估和实际。预估的执行计划是在执行之前由查询优化器计算;它表明优化器信任为最低消耗的执行计划。通常大约在几秒之内返回给用户。实际执行计划,另一方面,处理查询过程中实际执行的步骤。在查询完成后实际的计划被返回。有时,预估和实际的值会不同。在执行计划中值为定量数据。查看图1对于一些执行计划值的一个示例。


为什么预估和实际执行计划值不同?

有三个原因来解释为什么执行计划值不同。


1.预估执行计划不能被创建

在查询优化器对查询创建预估的执行计划之前,Algebrizer组件会验证查询。如果一个对象在查询中不存在,验证失败并且没有创建预估的执行计划。这种情况,当一个创建语句位于使用这个创建对象的相同批中。


2.陈旧的统计信息

SQL Server对每个索引创建关于每个列值的分布的统计信息。当查询优化器预估从一个操作返回的行数的时候,使用该信息,并且完全使用一个特定索引的消耗来预估。当在表中数据改变时,这些统计信息过期。如果查询优化器使用坏的统计信息,它会错误的计算执行计划的消耗。通过比较预估行数和实际行数,你可以看到在实际执行计划中一个操作的差异(见图1)。图1中高亮显示的差异是对表执行一个删除操作产生的。


3.并行性

如果安装SQL Server的机器有多个CPU,查询优化器会完成两次寻找最低消耗执行计划的过程;创建一个执行计划使用一个处理器,第二个执行计划利用多个处理器(并行性)。直到执行时才会决定运行这两个执行计划中的哪个。当用户请求查看预估执行计划,只有一个执行计划被显示。这个执行计划可能是、也可能不是当执行查询时查询引擎所选择的那个。


clip_image001

图1 比较EstimatedNumber of Rows和Actual Number of Rows


哪个执行计划更好?


一个预估执行计划几乎立即被返回,而实际执行计划不能。实际的执行计划给出了一个更加完整的图片,但是在生产环境中,为了获得实际执行计划而等待一个长时间运行的语句执行完成是不切实际的。

只有在实际执行计划中找到的最频繁使用信息,是从每个操作返回的实际行数。实际行数可以与预估行数比较。如果差异巨大,那么统计信息很可能过时了。在这种情况下更新统计信息可能会提高查询性能(查看TechNet文章“统计信息”获得更多关于这个话题的信息)。


另一种获得实际行数的方式是,检查表的索引统计信息的最后时间已更新。将该信息与数据库的活动联系起来,将会表名统计信息的陈旧情况。以下查询运行在sys.indexes表返回已更新的统计信息的最后日期:

1
2
3
4
5
6
USE YourDatabase
GO
SELECT  name  AS  index_name
, STATS_DATE(OBJECT_ID, index_id)  AS  StatsUpdated
FROM  sys.indexes
WHERE  OBJECT_ID = OBJECT_ID( 'YourSchema.YourTable' )


只在实际执行计划中找到的其他信息


Actual Rewinds和Rebinds的值只会应用到少数几个操作。这些值计数特定操作初始化的次数。大量的初始化可能导致高I/O使用。对于该话题更完整的涵盖,看看Grant Fritchey的书SQL Server执行计划

除了Actual Rewinds和Rebinds,Number of Executions在SQL Server 2008中引入。该值是一个操作被执行次数的计数。对一些操作,执行次数和返回行数相关,预估和实际的执行次数会根据预估和实际行数的不同而不同。在某些情况下,SQL Server不能预估执行计数,将会在Estimated Number of Executions显示值为1。


预估的执行计划包含预估的消耗,逻辑上导致实际执行计划包含实际消耗。然而,情况并非如此。正如之前提到的,计数值只是表明一个操作时间消耗上的相对昂贵程度。它不与任何实际值如CPU和I/O时间相关。


总结


图形化执行计划显示了所有操作的细节和它们将用于执行查询的顺序(或许是实际执行计划)。这使得它们对分析和优化慢查询是一个出色的工具。预估和实际的执行计划都有它们的优势和缺点。每个适合在特定的环境下。阅读该系列的第2部分和第3部分获得更多关于图形化执行计划的信息。


参考


.显示图形化执行计划(SQL Server Management Studio),TechNet Library -- http://technet.microsoft.com/en-us/library/ms178071(v=sql.105).aspx


.执行计划缓存和重用,TechNet Library -- http://technet.microsoft.com/en-us/library/ms181055(v=SQL.105).aspx


.Fritchey,Grant(2008),SQL Server执行计划,Simple Talk出版(本文使用2008版,在2013年第2版发行) -- http://technet.microsoft.com/en-us/library/ms191158.aspx




译者补充:


分析——》绑定——》优化


分析:检查,例如检查使用分隔标识符的表或列名称是否以数字开头,分析几乎是所有编程语言编译器的一项常规操作。


绑定:确定SQL语句所引用对象的特征检查请求语义是否有意义,例如检查From A join B的查询时,如果A是一个表B是一个存储过程,则绑定失败。


优化:类似于绑定,优化器一次只优化批处理中的一条语句,在编译器为该批处理生成执行计划并存储到plan cache之后将执行该计划的执行上下文(execute context)的特殊副本。sqlserver像缓存执行计划一样缓存执行上下文。sqlserver并不优化batch中的每条sql语句,他只优化那些访问表而且可能生成多个执行计划的语句,sqlserver优化所有的DML。只有被优化过的语句才会生成执行计划。


执行计划指标值


logical operation:基于微软查询处理概念模型的逻辑操作。例如,联接运算符的physical operation属性表示联接算法(nested loops,merge ,hash)物理运算符

logical operation属性表示逻辑联接类型(Inner join,outer join,semi join 等等)逻辑运算符

如果没有与该运算符关联的逻辑操作,则这项度量的值与physical operation相同


actual number of rows:从该运算符实际返回的行数(只显示在实际的计划中)


estimated I/O cost和estimated cpu cost:运算符在特定资源上的估计成本(I/O或CPU)这两个度量将帮助你确定运算符是否是I/O密集或CPU密集的

例如,你可以看到clustered index seek运算符主要与I/O有关,而hash match运算符主要与cpu有关


estimated operator cost:执行该操作的成本


estimated subtree cost:如前所述,他表示到当前节点为止整个子树的累积成本


estimated number of rows:该运算符预计的返回行数。在有些情况下,通过观察实际行数和估计行数之间的差异,你可以找出因统计信息不足或其他原因而导致的成本问题


estimated row size:你可能会奇怪为什么在实际的查询计划中没有显示该属性的实际值。因为你的表可能包含可变长度类型,表中行的大小各异


actual rebinds和actual rewinds:这两个度量仅与作为nested loops联接内侧的运算符有关,在其他运算符中,rebinds将显示为1,rewinds将显示为0

他们表示内部init方法被调用的次数。重新绑定次数和重绕次数之和等于联接外侧所处理的行数。重新绑定意味着联接的一个或多个参数发生更改后,必须重新计划

联接的内侧。重绕意味着任何相关参数都没有发生更改,可以重用之前的内侧结果集













本文转自UltraSQL51CTO博客,原文链接: http://blog.51cto.com/ultrasql/1734651,如需转载请自行联系原作者




相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
SQL 关系型数据库 MySQL
十九、使用explain分析你SQL执行计划
十九、使用explain分析你SQL执行计划
68 0
|
存储 SQL 分布式计算
工作常用之Hive 调优【三】 Explain 查看执行计划及建表优化
在查询时通过 WHERE 子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多,所以我们需要把常常用在 WHERE 语句中的字段指定为表的分区字段。
283 0
工作常用之Hive 调优【三】 Explain 查看执行计划及建表优化
|
SQL JSON 关系型数据库
JSON格式执行计划(6)—mysql执行计划(五十二)
JSON格式执行计划(6)—mysql执行计划(五十二)
|
SQL 存储 Oracle
一次搞定各种数据库SQL执行计划
执行计划(execution plan,也叫查询计划或者解释计划)是数据库执行 SQL 语句的具体步骤,例如通过索引还是全表扫描访问表中的数据,连接查询的实现方式和连接的顺序等。如果 SQL 语句性能不够理想,我们首先应该查看它的执行计划。
一次搞定各种数据库SQL执行计划
|
SQL JSON 关系型数据库
几个必须掌握的SQL优化技巧(四):使用Trace工具分析优化器执行计划
在应用的开发过程中,由于开发初期的数据量一般都比较小,所以开发过程中一般都比较注重功能上的实现,但是当完成了一个应用或者系统之后,随着生产数据量的急剧增长,那么之前的很多sql语句的写法就会显现出一定的性能问题,对生产的影响也会越来越大,这些不恰当的sql语句就会成为整个系统性能的瓶颈,为了追求系统的极致性能,必须要对它们进行优化。
352 0
几个必须掌握的SQL优化技巧(四):使用Trace工具分析优化器执行计划
|
SQL 关系型数据库 MySQL
二十二、查询分析器 EXPLAIN
二十二、查询分析器 EXPLAIN
142 0
二十二、查询分析器 EXPLAIN
|
存储 NoSQL JavaScript
MongDB查询性能分析——explain 结果详解
MongoDB 提供 db.collection.explain(), cursort.explain() 及 explain 命令获取查询计划及查询计划执行统计信息。 explain 结果将查询计划以阶段树的形式呈现。 每个阶段将其结果(文档或索引键)传递给父节点。 叶节点访问集合或索引。 中间节点操纵由子节点产生的文档或索引键。 根节点是MongoDB从中派生结果集的最后阶段。 阶段操作描述,例:
373 0
|
SQL 关系型数据库 MySQL