13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

SQL执行计划解析之执行计划基础上篇

执行计划,简单的说就是查询优化器计算的结果,表示执行被提交查询的效率***的方式。执行计划告诉你查询是如何被执行的,因此它是DBA诊断低性能查询的基础手段。

1.查询提交后发生了什么

当查询被提交到Sql Server DataBase之后,很多过程就开始工作,最终目的是将数据尽快返回给用户或者存储起来,同时保持数据的一致性。这些过程为每个提交到服务器的查询服务,因而有很多的不同的动作同时发生在服务器上,我们只关注T-SQL相关的事情,粗略的分为两个阶段:

在关系引擎中,查询优化器解析和处理查询,产生执行计划,然后执行计划被送到存储引擎(二进制方式),存储引擎使用执行计划来获取或更新数据。锁定、索引维护、事物等都发生在存储引擎里头。由于执行计划是由关系引擎产生的,我们将主要关注关系引擎。

1.1查询解析

T-sql查询到达服务器后去的***个地方就是关系引擎,它被传递给一个进程来检查拼写和形式,这个处理进程就是查询解析过程。解析过程的输出是一个解析树。解析树代表了执行查询的逻辑步骤。如果T-sql语句不是一个数据操纵语言(DML)声明就不会被优化,举个例子,对于创建table,系统只有一种“正确”的方式,那么就没有机会来提升性能。如果T-sql是DML声明,解析树就被传递给一个叫algebrizer的进程,algebrizer解析查询引用到的所有的对象、表、列的名字,并且识别列的类型(varchar(50) vs nvarchar(25)等),除此之外还要执行一个叫做聚合绑定 的过程来决定聚合的位置。algebrizer进程很重要,因为查询里可能包或了别名、同义词或者不存在的名字,这些需要被解析,或者查询引用了不存在的对象。algebrizer的输出是query processsor tree,二进制形式,然后被传递给了查询优化器。

1.2查询优化器

查询优化器决定了数据能否访问索引、使用哪种连接还有其他很多东西。这种决定是基于开销的,所需的cpu、io等。查询优化器将会产生并评估很多的计划(除非cache里已经有了),一般来说,选择开销***的那个,比如运行最快,使用最少的资源、cpu、I/O的那个。执行速度仍然是最重要的因素,如果能够更快返回结果,优化器会选择cpu密集型的过程。有时候优化器也会选择效率较低的计划,如果它认为花时间去评估很多的执行计划还不如采用较低效率的过程。如果你提交了一个非常简单的查询,比方说,单表查询、没有索引、没有聚合、没有计算,那么优化器就不会花时间来计算优化,而是简单的使用trival plan。

如果查询是非Trival的,那么优化器就会计算开销然后选择一个计划。因此它需要依赖sql server服务器维护的统计数据。统计数据是数据库收集的关于列和索引的数据,它描述了数据的分布(distribution)、唯一性(uniqueness)和选择性(selectivity)。构成统计数据的信息使用一个直方图(histogram)和表格(tabulation)来表示,它是从200个平均分布的数据点(data Points)取出来的表示特定数据的出现次数。这种“关于数据的数据”给优化器提供了计算所需的必要信息。

如果列和索引相关的统计数据存在,那么优化器就会使用它们来计算。缺省地,系统会为所有索引和那些用作谓词(predicate)、where子句的一部分、join on子句的一部分的列创建和更新统计数据。Table变量不会产生统计数据,优化器始终假定它只有一行而无视它真正的大小。临时表有统计数据,和***表的统计数据存储在同一个直方图里供优化器使用。

优化器使用这些统计数据和query processor tree一起决定***的执行计划。这就意味着,它需要测试一系列的计划,测试不同的join类型,组织join的顺序,尝试不同的索引等等,直到达成它认为的最快的执行计划。在这个计算中,每一步都赋予了一个数值,代表了优化器预估的时间开销(estimated cost),每一步的开销加起来就是执行计划的开销。

有必要指出,预估的开销毕竟是预估的,如果有无限的时间和完整的***的统计数据,优化器就能找到执行查询的***计划,但是优化器是试图在最短的时间找到***的执行计划,并且明显的,可用的统计数据的质量也是有限的,因此,虽然这个开销估算是个非常有用的手段,但是不能精确的反映现实。

优化器决定执行计划后,实际的执行计划就被创建并且存储进内存空间plan cache,除非相同的执行计划cache里已经存在。优化器产生可能的执行计划(potential plans),和cache里边已经存在的进行比较,如果匹配就是用cache里边的那个。

1.3查询执行

执行计划产生后,操作就转移到了存储引擎,在这里根据执行计划实际执行查询。这里不再详细讨论,除了一点,千辛万苦生成的执行计划和设计执行的可能并不一样,比方说一下情景:

1.4预估的和实际的执行计划

如前所述,有两种不同的执行计划,***个是由优化器产生的预估的执行计划(Estimated execution plan),操作符和步骤被贴了Logical标签,代表了优化器的观点,另一个是实际的执行计划(Actual execution plan),代表了实际发生的事情。

1.5重用执行计划

服务器产生执行计划开销是昂贵的,可能的情况下Sql Server会尽量保持和重用执行计划。执行计划生成后就被存储进内存Plan Cache。

执行计划并不是***驻留内存,它们会慢慢地根据age变化从系统消失,age的计算公式为执行计划的预估开销*被使用的次数,例如一个计划它的开销是10,被引用了5次,那么它的age值就是50。延迟写入(lazywriter)进程负责释放所有类型的cache(包括plan cache),它周期性地扫描cache里的对象,并每次减去一定的age值。如果达到下列条件,执行计划将会从内从中被清除:

  1. 系统需要更多内存
  2. age值达到了0
  3. 执行计划没有被任何连接(connection)所引用

执行计划也不是不可改变的,有些事件或动作会迫使执行计划重新编译。记住这些很重要,因为重新编译执行计划的开销可能非常大,下面的动作会导致执行计划重新编译:

  1. 改变查询中引用的表的结构或schema
  2. 改变了查询中用到的索引
  3. 删除了查询中用到的索引
  4. 更新了查询用到的统计数据
  5. 调用了函数sp_recompile
  6. 对查询用到的表的keys进行了大量insert或delete操作
  7. 对带有触发器的表,因inserted和deleted导致的明显增长
  8. 一个查询中混合了ddl和dml
  9. 查询执行中改变了SET选项
  10. 改变了查询使用的临时表的结构或schema
  11. 改变了查询中用到的动态试图(dynamic views)
  12. 改变了查询中的游标选项
  13. 改变了远程行集,就像在分布式分割试图(distributed partitioned view)里边
  14. 使用客户端游标时,改变了FOR BROWSE选项

1.6为何预估和实际的执行计划可能不同

一般情况下,你看到的预估执行计划和实际执行计划很可能是一样的,然而当环境改变时可能会导致二者的不同。

1.7执行计划的格式

  1. 图形方式
  2. 文本方式
  3.   
      
    1. SHOWPLAN_ALL 
    2. SHOWPLAN_TEXT 
    3. STATISTICS PROFILE 
  4. Xml方式
  5.   
      
    1. SHOWPLAN_XML 
    2. STATISTICS_XML 

原文链接:


网站名称:SQL执行计划解析之执行计划基础上篇
当前链接:http://cdbrznjsb.com/article/cosccoi.html

其他资讯

让你的专属顾问为你服务