SQL Server的查询优化器是一个基于成本的优化器。它为一个给定的查询分析出很多的候选的查询计划,并且估算每个候选计划的成本,从而选择一个成本最低的计划进行执行。实际上,因为查询优化器不可能对每一个产生的候选计划进行优化,所以查询优化器会在优化时间和查询计划的质量之间进行一个平衡,尽可能的选择一个“最优”的计划。

所以,查询优化器成为SQL Server中最重要的一个组件,并且影响着SQL Server的性能。选择正确或错误的执行计划意味着查询执行时间可能存在着毫秒的,几分钟,甚至几个小时之间的差异。

了解查询优化的内部机制,可以帮助DBA和开发人员能够编写更好的查询,或者给查询优化器提供信息使得它可以产生有效的执行计划。本系列文章讲述的查询优化器的内部运作的知识,此外,还会告诉你如何使用查询优化器的相关信息进行性能诊断。

 下面,我们首先来看看:查询优化器是如何工作的。

  在SQL Server数据库引擎的核心是两个主要部分组成:存储引擎查询处理器(也被称为关系引擎)。存储引擎负责在磁盘和内存之间以最优化的方式读取数据,同时维护数据的完整性。查询处理器,顾名思义,接受提交给SQL Server所有的查询,并且为产生他们的最佳执行计划,然后执行该计划,并提供所需的结果。

我们将查询以T-SQL的形式提交给SQL Server。因为SQL语句是一个高层抽象的声明性的语言,它仅仅只是定义了要从数据库中获取什么样的数据,而没有告诉如何去获取这些数据(或者说,没有定义获取数据的方法和步骤)。所以,对于SQL Server所接受到的每一个查询,查询处理器的首要任务就是产生一个计划,这个计划就描述了如何去执行查询,之后就由存储引擎去执行这个计划了。

为了确保已经达到在查询处理器认为是最好的计划执行查询,查询处理器执行不同的步骤,整个查询处理过程如图所示:

  当然,上面的图只是一个最简单的示例图,下面,给大家看另外一个图,体会一下一个查询处理的过程:

我们在后续的文章中会看到每一个步骤的详细讲解与应用,下面我们就简单的介绍图中的一些步骤(为了简单起见,我们以第一幅图为例子)

 1. Parsing 和Binding(解析与绑定):在一个查询提交给了数据库之后,首先就要被进行语法的解析,如果这个查询的语法是没有问题的,那么这个Parsing过程的输入结果就是一个逻辑树,在这个逻辑树种每一个节点都表示了这个查询进行的每个操作,例如读取某个表,进行inner join等。

下面,给大家看一个逻辑树的例子,对于下面的查询:

  产生的逻辑树如下:

  这个过程就是编译原理的一个文法词法的解析。

  谈完了Parsing,之后的操作就是Binding了,这个操作现在改名字为Algebrizer。这个操作主要就是检查解析产生的逻辑树中的对象是否存在,例如Customer是否是数据库中的表,CustomerID字段是否在Customer表中等。

  经过了这个Binding之后,就会产生另外一个树形的数据结构,传递给下一个步骤。

2. 查询优化。这个过程主要是使用上述过程中的Algebrizer Tree进行优化的处理过程,我们这里大体的可以将这个优化的处理过程分为两个步骤:

  a. 产生执行计划。在这个过程中,查询优化器会使用之前的树,产生执行计划。这个过程主要是将树上的逻辑操作转换为物理操作(其实就是存储引擎可以调用的方法,这些方法就是实实在在的去读取数据的)。

  b. 估算每个执行计划的成本。一个逻辑操作可以有很多的物理操作与其对应,而每个物理操作的成本不一样,同时,也没用所谓的“什么物理操作比其他的物理操作更优” ,一切视情况可认定。在这个过程中产生很多的候选执行计划,并且查询优化器会综合考虑很多的情况,选择一个它认为“比较优”的计划,传递给存储引擎。

  3. 查询的执行与计划的缓存。这个过程比较简单了,主要是存储引擎去执行执行计划,同时为了避免相类似的SQL查询重新编译,使用过的执行计划会被缓存在计划缓存池中。

  基本是,我们可以看出,查询优化的过程就是一个将逻辑操作映射为物理操作的过程。

 

 

为了得到最好的计划,查询优化器必须在某些条件的限制下,尽可能多的创建和评估大量的候选执行计划。看到这里,就有一点需要注意了“查询优化器是尽可能多的创建候选执行计划”,而不是为一个查询产生所有的执行计划。在SQL Server中,我们把一个查询产生的候选执行计划的集合称之为“搜索空间(search space)”。很显然,搜索空间中的所有的执行计划都返回相同的结果。

给一张示意图,让大家更好理解一点,如下所示:

  注:图中的Search Space中的曲线代表执行计划

  从理论上说,为了找到最佳的执行计划的查询,基于成本的查询优化器应该生成搜索空间中存在的所有可能的执行计划,并正确估计每个计划的成本。然而,一些复杂的查询可能有成千上万,或者甚至数百万可能的执行计划,查询优化器不可能去产生并评估一个查询的每一个候选的执行计划,如果那样,评估所有计划的时间会非常的长,并且严重影响查询的整体的执行时间。

查询优化器必须优化的时间和执行计划的质量之间取得平衡。例如,如果查询优化器花1秒钟的时间找到了一个比较好的执行计划,并且这个计划的执行时间是1分钟,那么这个时候,就没有必要再去花费5分钟的时间去为这个查询找更优的执行计划。因此SQL Server不会做一个详尽的全部查找,而是尽快找到一个合适的有效的计划。由于查询优化器是有时间限制的,那么就可能选择的计划可能是最优方案,也有可能只是一些接近最优的方案。

候选的执行计划是在查询优化器的内部通过使用转换规则,启发式算法产生的。候选的执行计划在优化过程中一直保存在称之为“Memo(中文翻译可能为“备忘录”,以后我们就直接使用英文名称,很多的技术术语翻译过来之后就变味了)”的内存组件中。从这里我们就可以知道:如果为了复杂的查询产生所有的候选执行计划势必会占用大量的内存。

  我们这里只是简单的介绍一下候选执行计划的产生,后面我们会对每一个步骤进行详细的分析。

执行计划成本估算

  查询优化器需要为产生的候选的执行计划进行成本的估算,从而选择一个成本最低的。为了估算一个计划的成本,查询优化器会使用一些成本估算的公式来计算一个计划的成本,这些成本估算公式会考虑很多资源的使用,例如CPU,I/O,内存等。成本估算主要是取决于算法中采用的物理操和估算的将要处理的数据记录的量(估算数据记录的量也被称之为“基数估算”)。

为了便于进行基数估算,SQL Server会使用并且维护统计数据(statistics),统计数据描述了表中数据的值的分布情况,或者简单的理解为“元数据-描述数据的数据”。一旦采用基数估算得出了吗,每个操作的成本和对资源的要求,那么查询优化器就会将这个成本数值进行累计,从而得出整个就会的成本。我们这里不会讨论过多与统计数据相关的知识,在后面中会详细的讲述。

[原文参考: http://tech.it168.com/a2012/0329/1332/000001332016.shtml ,感谢原文作者]

SQL Server查询优化器的工作原理的更多相关文章

  1. SQL Server 查询优化器运行方式

    一.结合实际,谈索引使用的误区 理论的目的是应用.虽然我们刚才列出了何时应使用聚集索引或非聚集索引,但在实践中以上规则却很容易被忽视或不能根据实际情况进行综合分析.下面我们将根据在实践中遇到的实际问题 ...

  2. SQL Server 查询优化 索引的结构与分类

    一.索引的结构 关系型数据库中以二维表来表达关系模型,表中的数据以页的形式存储在磁盘上,在SQL SERVER中,数据页是磁盘上8k的连续空间,那么,一个表的所有数据页在磁盘上是如何组织的呢?分两种情 ...

  3. 人人都是 DBA(III)SQL Server 调度器

    在 SQL Server 中,当数据库启动后,SQL Server 会为每个物理 CPU(包括 Physical CPU 和 Hyperthreaded)创建一个对应的任务调度器(Scheduler) ...

  4. SQL Server 统计信息(Statistics)-概念,原理,应用,维护

    前言:统计信息作为sql server优化器生成执行计划的重要参考,需要数据库开发人员,数据库管理员对其有一定的理解,从而合理高效的应用,管理. 第一部分 概念 统计信息(statistics):描述 ...

  5. SQL Server数据库快照的工作方式

    SQL Server数据库快照的工作方式 翻译自:How Database Snapshots Work 最近有一个帖子<errorlog中的异常信息rolled forward 和rolled ...

  6. SQL Server 优化器特性导致的内存授予相关BUG

    我们有时会遇到一些坑,要不填平,要不绕过.这里为大家介绍一个相关SQL Server优化器方面的特性导致内存授予的相关BUG,及相关解决方式,也顺便回答下邹建同学的相关疑问. 问题描述 一个简单的查询 ...

  7. SQL Server优化器特性-隐式谓词

    我们都知道,一条SQL语句提交给优化器会产生相应的执行计划然后执行输出结果,但他的执行计划是如何产生的呢?这可能是关系型数据库最复杂的部分了.这里我为大家介绍一个有关SQL Server优化器的特性- ...

  8. Win8、Win10进入SQL server配置管理器

    使用 WIN8.WIN10 访问 SQL Server 配置管理器 因为 SQL Server 配置管理器是 Microsoft 管理控制台程序的一个管理单元而不是单独的程序,所以,当运行 Windo ...

  9. 如何启动 SQL Server Agent(SQL Server 配置管理器)

    如何启动 SQL Server Agent(SQL Server 配置管理器) SQL Server 2008 R2 其他版本   4(共 6)对本文的评价是有帮助 - 评价此主题 可以从 SQL S ...

随机推荐

  1. [UWP]如何使用代码创建DataTemplate(或者ControlTemplate)

    1. 前言 在UWP中DataTemplate是一个十分重要的功能,并且几乎无处不在,例如DataGrid中的DataGridTemplateColumn: <controls:DataGrid ...

  2. ASP.NET MVC5+EF6+EasyUI 后台管理系统(92)-打印EasyUI 的datagrid表格

    前言 应用系统有时候需要打印Datagrid的表格内容,我们本节就来学习打印datagrid内容 打印主要使用:web打印(我们之前有讲过web打印插件jqprint) + 将datagrid重新编制 ...

  3. Jenkins - 构建Allure Report

    前言 本文为Pytest+Allure定制报告进阶篇,集成Jenkins,在Jenkins中直接生成报告,更方便测试人员查看. 一.安装插件allure-jenkins-plugin 1.进入系统管理 ...

  4. Mysql权限操作、用户管理、密码操作

    Mysql的权限 mysql中存在4个控制权限的表,分别为user表,db表,tables_priv表,columns_priv表. mysql权限表的验证过程为: 先从user表中的Host,Use ...

  5. hdu 5584 LCM Walk

    没用运用好式子...想想其实很简单,首先应该分析,由于每次加一个LCM是大于等于其中任何一个数的,那么我LCM加在哪个数上面,那个数就是会变成大的,这样想,我们就知道,每个(x,y)对应就一种情况. ...

  6. c++入门之—运算符重载和友元函数

    运算符重载的意义是:将常见的运算符重载出其他的含义:比如将*重载出指针的含义,将<<与cout联合使用重载出输出的含义,但需要认识到的问题是:运算符的重载:本质仍然是成员函数,即你可以认为 ...

  7. 2 JAVA 项目名称前红色叹号如何解决

    1 Java 项目前出现红色叹号Eclipse找不到项目需要的JAR包,可以在这里面解决: ① 右键点击项目,选择[Build Path].[Configure Build Path...] ② 在这 ...

  8. 【知乎】WinForm 与 WPF的区别

    你想上班 那么针对公司需求学如果只是自己写着玩 那么区分一下1.你的程序运行在 自己机器a.一个工具而已 要的是cooooooool 那么WPFb.一个工具而已 要的是useful easy 那么wi ...

  9. python中random模块

    random与numpy.random对比: 1.random.random():生成[0,1)之间的随机浮点数: numpy.random.random():生成[0,1)之间的随机浮点数: num ...

  10. rbac组件引用

    一. 批量操作思路 # 待新增 路由系统中有,但是数据库中还没有 路由系统的集合 - 数据库中权限集合 # 待更新 路由系统中有,数据库中也有, 只是更改了一些信息 路由系统的集合 & 数据库 ...