执行计划的生成

原文:执行计划的生成

  SQL Server使用许多技术来优化资源消耗:

  • 基于语法的查询优化;
  • 无用计划匹配以避免对简单查询的深度优化;
  • 根据当前分布统计的索引和连接策略;
  • 多阶段的查询优化以控制优化开销;
  • 执行计划缓冲以避免重新生成执行计划;

  以上技术按以下顺序执行:

  • 解析器;
  • 代数化器;
  • 查询优化器;
  • 执行计划生成,缓冲和hash计划生成;
  • 查询执行;

  其执行顺序如下:

  

一、解析器(parser)

  当查询被提交时,SQL Server将它传递给关系引擎中的解析器。

  •   关系引擎-负责解析、名称和类型解析、优化和按照查询执行计划执行查询并从存储引擎请求数据;
  •   存储引擎-负责数据访问、修改、缓冲;

  解析器检查进入的查询,验证其语法是否正确。如果发现一个语法错误则查询被终止。如果多个查询作为一个批被一起提交,如下:

CREATE TABLE t1(c1 INT)
INSERT INTO t1 VALUES(1)
AELECE * FROM t1    --注意,SELECT拼写错误
GO

  解析器检查整个批的语法并在发现语法错误时撤销整个批(批中可能出现多个语法错误,但是解析器发现第一个错误后就不再继续,所以批中有语法错误时代码是一行都不会执行的。)在验证查询的语法时,解析器为代数化器生成一个称为解析树的内部数据结构。解析器和代数化器被统称为查询编译。

二、代数化器(Algebrizer)

  解析器生成的解析树被传递到代数化器处理。代数化器解析不同对象的所有名称,也就是T-SQL引用的表、列等。它还确认所有被处理的不同数据类型,甚至还检查聚合(GROUP BY、MAX)的位置。所有这些验证和解析的输出是被称为查询处理器树的二进制数据集。

  为了了解代数化器的运行,提交以下批查询:

CREATE TABLE t1(c1 INT);
INSERT INTO t1 VALUES(1);
SELECT 'Before Error',c1 FROM t1 AS t;--下面的没执行
SELECT 'error',c1 FROM no_t1; --no_t1表不存在
SELECT 'after error' c1 FROM t1 AS t;

  对于以上语句,头3条被执行了。错误及之后的语句被撤销了。

  如果查询包含一个隐含的数据转换,规范化进程在查询树中添加一个正确的步骤。该进程还执行一些基于语法的优化。如:

SELECT * FROM Person WHERE Id BETWEEN 100 and 150

  则基于语法的优化将转换该查询的语法。

  对于大部分数据定义语言(DDL)语句(如CREATE TABLE、CREATE PROC等)来说,在通过代数化器之后,该查询直接被编译以执行,因为优化器不需要在多种处理策略中选择。对于特别的DDL语句CREATE INDEX,优化器可以根据其他表上现有的索引来决定一个有效的处理策略。

  因此,执行计划中不会看到对CREATE TABLE的引用,但是会看到CREATE INDEX的引用。如果规范化的查询时一条数据操纵语言(DML)语句,则查询处理器树被传递给优化器以决定该查询的处理策略。

  

三、优化

  根据查询的复杂度,包括引用的表和可用的索引数量,查询处理器树中包含的查询可能由多种知心方式。完全比较所有执行查询方式的开销可能要花费较多的时间,有时即使找到最优化查询也是得不偿失。为了避免过多的优化开销,优化器采用不同的技术,包括:

  • 无用计划匹配;
  • 多阶段优化;
  • 并行计划优化;

  1、无用计划匹配

  有时候可能只有一种执行查询的方式。例如,堆表只能通过表扫描来获取数据,为了避免浪费时间来优化这种查询,SQL Server维护了一个无用计划列表供选择,如果优化器在无用列表中发现与查询有匹配的计划,则生成相似的计划而不再做任何优化。

   2、多阶段优化

  对于复杂的查询,需要分析的替代处理策略数量可能很大,评估每个选择可能花费很长的时间。因此,优化器不分析所有可能的处理策略,而是将他们分为几种配置,每个配置含不同的索引和连接技术。

  索引变种考虑不同的索引特性,单列索引、复合索引、索引列顺序、索引密度等。相似地,连接变种考虑SQL Server中可用的不同连接技术:嵌套循环连接、合并连接和哈希匹配。

   

  优化器考虑WHERE子句中引起的列的统计以评估索引和连接策略的有效性。根据当前的统计,它在多个优化阶段中评估配置的开销。开销包括许多因素,包含执行查询所需要的CPU、内存的使用和磁盘I/O。每个优化阶段之后,优化器评估处理策略的开销。如果开销足够经济,优化器停止在优化阶段进一步循环并退出优化过程。否则继续在优化阶段中循环以确定一个高成本效益的处理策略。

  有时候查询可能太复杂,以至优化器必须广泛地在优化阶段中循环。在优化查询时,如果发现处理策略的开销高于并行开下阈值,则使用多个CPU评估处理该查询的开销。否则,优化器使用串行计划。

  • 缓冲计划的大小;
  • 用于编译该计划的CPU周期;
  • 使用的内存量;
  • 编译时间;

  优化水平属性说明优化器中出现的处理类型。在这个例子中,FULL表示优化器进行了完全优化。这在属性“语句终端原因”中进一步提示,原因是“找到足够好的计划”。所以,优化器花费21ms来捕捉到这种情形下被认为足够好的计划。还可以查看执行计划的查询计划hash值。

  第二个优化器信息原来是动态管理视图sys.dm_exec_query_optimizer_info。这个DMV是优化事件的集合体,它不会显示给定查询的单独优化,但是可以跟踪行的优化。这不能直接用于调整单个查询,但是如果打算随时减少工作负载的开销,跟踪这些信息能够能帮助确定查询调整是否产生正面的影响,至少在优化时间方面,一些返回的数据只用于SQL Server内部。.

  执行如下查询:

SELECT Counter,Occurrence,Value FROM sys.dm_exec_query_optimizer_info

  在一组优化之前和之后运行这个查询,可以看到完成的优化数量和类型的变化。

  3、并行计划优化

  优化器在评估处理查询的开销时使用并行计划考虑各种因素。

  • 可用于SQL Server的CPU数量;
  • SQL Server版本;
  • 可用内存;
  • 执行的查询类型;
  • 给定流中处理的行数;
  • 活动的冰法连接数量;

  如果只有一个CPU可用于SQL Server,优化器不会考虑并行计划。可用于SQL Server的CPU数量可以使用SQL Server配置的affinity mask设置来显示。affinity mask值是一个位图,一位代表一个CPU,最右边的位置代表CPU0。例如,在8路的计算机只允许SQL Server使用CPU0-CPU3,执行如下语句:

USE master
EXEC sp_configure 'show advanced option', '1'
RECONFIGURE
EXEC sp_configure 'affinity mask', 15 --位图:00001111
RECONFIGURE

  这个配置立即生效。affinity mask是一个特殊的设置,建议只在剥夺SQL Server控制权有意义的情况下使用它,例如有多个运行在相同计算机上的SQL Server实例并且希望它们互相隔离时, 要设置超过32个处理器,必须使用只在SQL Server64位版本上可用的affinity64 mask选项。还 可以使用affinity mask I/O选项来将I/O绑定到特定的处理器集。

  即使多个CPU可用于SQL Server。一个并行查询可以使用的CPU最大数量由SQL Server配置中的max degree of parallelism设置管理。默认值为0,允许所有CPU(affinity mask设置可用的)用于并行查询。

  如果希望运行并行查询使用不超过CPU0-CPU3中的2个CPU,执行以下语句:

USE master
EXEC sp_configure 'show advanced option','1'
RECONFIGURE
EXEC sp_configure 'max degree of parallelism',2    --设置查询最高可使用2个CPURECONFIGURE

  这个修改立即生效,不需要重启。max degree of parallelism设置页可以使用MAXDOP查询提示 

  在查询级别上控制:

SELECT * FROM Person WHERE Name='张三' OPTION(MAXDOP 2)

  修改max degree of parallelism设置最好由系统需求决定。为了限制与操作系统争用,通常将   max degree of parallelism设置为比服务器CPU数量少1,并将affinity mask也设置为这些CPU。

  因为并行查询需要更多内存,所以优化器在选择并行计划之前需确定可用内存的数量。所需内存的数量随着并行程序而增加。如果给定并行程度的并行计划内存需求不能满足,SQL Server将自动降低并行程度或者在给定的工作负载上下文中完全放弃并行计划。

  具有非常高的CPU开销的查询时并发计划的最佳候选。如包含连接大的表,执行大量的聚合运算,以及排序大的结果集。对于通常在事务处理应用程序中找到的简单查询来说,初始化、同步和停止并行计划所需的额外调整超过了潜在的性能优势。

  查询是否简单通过比较估算的执行时间和开销阈值来确定。这个开销阈值由SQL Server配置的cost threshold for parallelism设置控制。默认情况下,这个设置为5,意味着如果串行计划估算的执行时间超过5秒,则优化器考虑使用并行计划。例如,要将开销阈值修改为6秒,执行以下语句:

USE master
EXEC sp_configure 'show advances option','1'
RECONFIGURE
EXEC sp_configure 'cost threshold for parallelism',6
RECONFIGURE

  这个修改不需要重启立即生效。如果只有一个CPU可用于SQL Server,这个设置将被忽略。OLTP系统会因为并行性阈值设置太低而受到损害。通常将这些值增加到15-25秒之间比较有利。

  DML操作查询(INSERT、UPDATE和DELETE)串行查询。但是,INSERT语句的SELECT部分和UPDATE或DELETE语句的WHERE语句可以并行执行。实际的数据修改被严格地应用到数据库。而且,如果优化器确定所影响的行太少,它不会引入并行操作符。

  注意,即使在执行时,SQL Server确定当前系统工作负载和配置信息是否允许并行查询计划。如果允许并行查询计划,SQL Server确定现成的最有数量并将查询的执行分布到这些线程。当查询开始并行执行,它使用相同的线程数量直到完成。SQL Server在下次执行并行查询时重新检查最优线程数量。

  处理策略被使用串行或并行计划定稿之后,优化器为查询生成后执行计划。该执行计划包括优化器确定的执行该查询的详细处理策略。这包括诸如数据检索、结果集连接、结果集排序等步骤。

  生成的查询计划被保存在计划缓冲中供未来使用。

时间: 2024-09-21 04:14:01

执行计划的生成的相关文章

Pig源码分析: 简析执行计划的生成

摘要 本文通过跟代码的方式,分析从输入一批Pig-latin到输出物理执行计划(与launcher引擎有关,一般是MR执行计划,也可以是Spark RDD的执行算子)的整体流程. 不会具体涉及AST如何解析.如何使用了Anltr.逻辑执行计划如何映射.逻辑执行计划如何优化.MR执行计划如何切分为MR Job,而是从输入一批Pig DSL到待执行的真正执行计划的关键变化步骤(方法和类). 执行计划完整解析 入口处书Main类的main函数 /** * The Main-Class for the

《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》一1.1 生成执行计划

1.1 生成执行计划 在Oracle中,任何一条语句在解析过程中都会生成一个唯一的数值标识,即SQL_ID.而同一条语句,在解析过程中,可能会因为执行环境的改变(例如某些优化参数被改变)而生成多个版本的游标,不同的游标会有不同的执行计划.每个游标都会按顺序赋予一个序列号,即CHILD_NUMBER,一条语句生成的第一个游标的CHILD_NUMBER为0:相应的,Oracle会为每个执行计划生成一个哈希值以作区分.而多个不同版本的游标,其执行计划可能会相同,也可能不同. 因此,我们可以知道,一条合

利用Oracle执行计划机制提高查询性能

oracle|性能|执行 消耗在准备利用Oracle执行计划机制提高查询性能新的SQL语句的时间是Oracle SQL语句执行时间的最重要的组成部分.但是通过理解Oracle内部产生执行计划的机制,你能够控制Oracle花费在评估连接顺序的时间数量,并且能在大体上提高查询性能. 准备执行SQL语句 当SQL语句进入Oracle的库缓存后,在该语句准备执行之前,将执行下列步骤: 1) 语法检查:检查SQL语句拼写是否正确和词序. 2) 语义分析:核实所有的与数据字典不一致的表和列的名字. 3) 轮

Sql Server之旅——第十一站 简单说说sqlserver的执行计划

我们知道sql在底层的执行给我们上层人员开了一个窗口,那就是执行计划,有了执行计划之后,我们就清楚了那些烂sql是怎么执行的,这样 就可以方便的找到sql的缺陷和优化点. 一:执行计划生成过程 说到执行计划,首先要知道的是执行计划大概生成的过程,这样就可以做到就心中有数了,下面我画下简图: 1. 分析过程 这三个比较容易理解,首先我们要保证sql的语法不能错误,select和join的表是必须存在的,以及你是有执行这个sql的权限,对不对... 这样我们就走完了执行计划生命周期的第一个流程. 2

MySQL执行计划extra中的using index 和 using where using index 的区别

原文:MySQL执行计划extra中的using index 和 using where using index 的区别   本文出处:http://www.cnblogs.com/wy123/p/7366486.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他)   mysql执行计划中的extra列中表明了执行计划的每一步中的实现细节,其中包含了与索引相关的一些细节信息其中跟索引有关的using index

Oracle 历史SQL语句执行计划的对比与分析

    基于CBO优化器的环境中,SQL执行计划的生成依赖于统计信息的真实与完整.如列的离散度,列上的直方图,索引的可用性,索引上的聚簇因子.当这些信息是真实完整的情况下,CBO优化器通常都可以制定最优的执行计划.也正因此CBO优化器也灵活,难以控制,任一信息的不真实或缺失都可能导致执行计划发生变化而产生多个版本.经常碰到的情形是之前的某个SQL语句前阵子还不是TOP SQL,而最近变成了TOP SQL.或者说之前尽管是TOP SQL但,但最近尽然成了TOP 1.对于此情形,我们可以比对SQL语

深入Oracle优化器:一条诡异执行计划的解决之道

CBO计算成本并选择最佳执行计划的至关重要输入物就是表和索引的统计信息,过旧或错误的统计信息则可能导致一个性能极差的执行计划被错误地选中.本文将以一个案例展示诡异的统计信息如何影响执行计划的生成. 1案例介绍    这是一个简单的sql,近两个月来对于告警明细表(分区)做月度汇总查询时,总是出现了异常缓慢的情况. 测试SQL: 字段NEALARM_TIME是固定条件,字段RELATED_EMS_CUID是不固定的(这些不固定条件的选择性都不强),分区裁剪到的分区有着1~3月份的数据. 关于HIS

SQLServer中的执行计划缓存由于长时间缓存对性能造成的干扰

原文:SQLServer中的执行计划缓存由于长时间缓存对性能造成的干扰   本文出处:http://www.cnblogs.com/wy123/p/7190785.html  (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他)   先抛出一个性能问题,前几天遇到一个生产环境性能极其低下的存储过程,开发人员根据具体的业务逻辑和返回的数据量,猜测到这个存储过程的执行应该不会有这么慢.当时意识到可能是执行计划缓存的问题,因为当

执行计划组件、组件、老化

原文:执行计划组件.组件.老化 一.执行计划缓冲 优化器生成的执行计划保存在SQL Server内存池中的一个特别部分,被称为计划缓冲或过程缓冲.过程缓冲是SQL Server缓存的一部分.在缓冲中保存计划可使SQL Server避免在重新提交相同的查询时再次通过整个查询优化过程运行.SQL Server支持不同的技术,如:计划缓冲老化,计划缓冲类型来增加缓存的计划的可重用性.它还保存两个被称为hash和查询计划hash的二进制值. 二.执行计划组件 优化器生成的执行计划包含两个组件: 查询计划