赞
踩
注:由于查询优化器涉及面很广也比较复杂,作者也没有完全领会,本文主要来自书籍<<数据库查询优化的艺术: 原理解析和SQL性能优化>>,如果涉及到版权,请告知作者,删除本文。
MySQL查询语句在数据库中的执行分为5个阶段,具体如下:
数据库接收用户输入的SQL语句,准备执行。
对输入的SQL语句进行词法分析、语法分析,得到语法分析树。在这个阶段,输入的是一条SQL语句,输出的是一棵多叉树。
根据语法树和系统的元信息进行语义检查,本阶段是对语法分析树进行逻辑判断,树的结构不发生变化。对语法分析树上的各个节点进行语义分析,判断对象是否存在、是否重名等,对不合语义的地方报告错误。
SQL优化通常包括两项工作:一是逻辑优化、二是物理优化。这两项工作都要对语法分析树的形态进行修改,把语法分析树变为查询树。其中,逻辑查询优化将生成逻辑查询执行计划。在生成逻辑查询执行计划过程中,根据关系代数的原理,把语法分析树变为关系代数语法树的样式,原先SQL语义中的一些谓词变化为逻辑代数的操作符等样式,这些样式是一个临时的中间状态,经过进一步的逻辑查询优化,如执行常量传递、选择下推等(如一些节点下移,一些节点上移),从而生成逻辑查询执行计划。在生成逻辑查询计划后,查询优化器会进一步对查询树进行物理查询优化。物理优化会对逻辑查询进行改造,改造的内容主要是对连接的顺序进行调整。SQL语句确定的连接顺序经过多表连接算法的处理,可能导致表之间的连接顺序发生变化,所以树的形态有可能调整。物理查询优化除了进行表的连接顺序调整外,还会使用代价估算模型对单个表的扫描方式、两表连接的连接算法进行评估,选择每一项操作中代价最小的操作为下一步优化的基础。物理查询优化的最终结果是生成最终物理查询执行计划。
在SQL执行阶段,依据物理查询计划执行查询,逐步调用相关算法进行执行。算法包括一趟算法、嵌套循环连接、基于排序的两趟算法、基于散列的两趟算法、基于索引的算法、使用超过两趟的算法等。
查询优化器在逻辑优化阶段主要解决的问题是: 如何找出SQL语句等价的变换形式,使得SQL执行更高效。一条SQL查询语句结构复杂,包含多种类型的字句,优化操作依赖于表的一些属性(如索引和约束等)。可用于优化的思路包括:
传统的联机事务处理(OLTP)使用基于选择(SELECT)、投影(PROJECT)、连接(JOIN)3种基本操作相结合的查询,这种查询称为SPJ查询。数据库在查询优化的过程中,会对这3种基本操作进行优化。优化的方式如下:
逻辑优化阶段使用的启发式规则通常包括如下两类:
查询优化器在物理优化阶段,主要解决的问题如下:
在查询优化器实现的早期,使用的是逻辑优化技术,即使用关系代数规则和启发式规则对查询进行优化后,认为生成的执行计划就是最优的。在引入了基于代价的查询优化方式后,对查询执行计划做了定量的分析,对每一个可能的执行方式进行评估,挑出代价最小的作为最优的计划。目前数据库的查询优化器通常融合这两种方式。
查询代价估算的重点是代价估算模型,这是物理查询优化的依据。除了代价模型外,选择率对代价求解也起着重要作用。
单表扫描需要从表上获取元组,直接关联到物理IO的读取,所以不同的单表扫描方式,有不同的代价。
索引是 建立在表上的,本质上是通过索引直接定位表的物理元组,加快数据获取的方式,所以索引优化的手段应该归属到物理查询优化阶段。
关系代数的一项重要操作是连接运算,多个表连接是建立在两表之间连接的基础上的。研究两表连接的方式,对连接效率的提高有着直接的影响。
多表连接算法实现的是在查询路径生成的过程中,根据代价估算,从各种可能的候选路径中找出最优的路径(最优路径是代价最小的路径)。多表连接算法需要解决两个问题:
在数据库内部,根据功能不同,可以划分出多个模块,不同模块之间有的关系紧密,有的关系松散。查询优化器是其中的一个功能模块,是实现查询优化技术的模块。下面介绍数据库中与查询优化器相关的模块:
语法分析器是查询优化器的输入。理解查询优化器,从语法分析器开始,将是个好的开端。因为不同对象有着不同的数据结构,数据结构成员是对象属性的载体,而语法分析器把一个SQL分解为众多数据结构体并给数据结构赋值,这样才能被查询优化器逐项获取并用与计算,比如逻辑查询优化有一条"常量传递"规则,如果没有语法分析器分解条件,也不可能推知列值是常量,也不可能有此优化。
查询优化器是执行器的前端输入部分。查询优化器计划一条SQL的具体执行方式和步骤 ,执行器具体去完成计划中的每一步。在实践中,一条SQL最耗时的阶段多发生在执行阶段。如果查询计划做得不好,则执行起来非常耗时。
缓冲区有多种多样,比如与数据相关的缓冲区(如从存储设备加载数据到内存)、与实现过程相关的辅助缓冲区(如排序用到的临时表或内存块),与功能模块相关的缓冲区(如日志缓冲区)等。优化器主要是对SQL输入进行逻辑方式的变换,没有涉及数据部分,只涉及对数据量的估计。当估算排序空间的时候,会涉及排序缓冲区;当估算数据IO的时候,需要考虑数据是否在数据缓存中。所以,查询优化器与数据缓冲区有一定的关系。
MySQL数据库的查询优化器使用了基于代价的查询执行计划估算,所以依赖于被查对象的各种数据,而数据是动态变化的,如表的元组数。如果实时获取这些数据,系统计算的开销会比较大。为了避免这样的问题,定期或者根据需要统计这些数据,则比较切合实际。优化器在物理优化阶段,需要对单表读取开销,两表连接开销,多表连接顺序开销等进行比较,比较基于的就是一些基础数据的值,这些数据通常不会被实时更新,所以优化器有时做出的计划未必是最合适的。
优化器做物理查询优化需要利用索引提高单表扫描效率,进而减少了多表连接时的元组数,所以确定哪些索引可用、怎么有效利用索引等都在查询优化器中得到体现。
MySQL 查询优化器的主要功能是完成SELECT语句的执行,在保证SELECT语句正确执行之外,还有一个重要的功能,就是使用关系代数、启发式规则、代价估值模型等不同种类的技术,提高SELECT语句的执行效率。
MySQL 查询 优化 器 实现 第 2 章介绍 的 大多数查询优化技术,这些 技术, 用于 对 SPJ 和 非 SPJ 类型 的 查询 语句 进行 优化。
下面将从整体上介绍MySQL查询优化器, 分别对MySQL 查询优化器的执行过程、架构、层次、设计 思想、主要概念、代码结构上宏观探讨MySQL查询优化器的实现。
MySQL查询执行过程分为4个阶段,如下所示:
MySQL查询优化器在逻辑查询执行计划阶段,机遇关系代数规则和启发式规则,把用户指定的SQL经过"等价"的代数转换,变为一种更节省IO的执行序列,执行起来更为高效。
MySQL查询优化器在物理查询执行计划阶段,在解决多表连接的问题时,有两套算法:一是用户指定表连接次序的算法;二是混杂了贪婪和穷举思想的算法,解决的是较多表的连接和非用户指定连接次序的多表连接,但不能保证得到最优的查询执行计划。
MySQL查询优化器设计精巧,但层次不够清晰,V5.6之后的版本,混乱状态有所改善,但MySQL查询优化器实用而高效,在充分利用索引的基础上,实现了很多查询优化技术,有很多精巧之处值得学习探索。
MySQL查询优化过程中,查询优化器通过JOIN对象的方法,如JOIN.prepare()、JOIN.optimize(),完成优化工作。JOIN.prepare()完成的查询优化主要包括:子查询的冗余子句消除、IN类型子查询优化、将ALL/ANY等类型的子查询转换为MIN/MAX等操作,这是对简单子查询进行的优化;JOIN.optimize()函数完成的查询优化主要包括:子查询上拉,把外连接优>化为内连接,把嵌套连接消除,WHRER子句、JOIN/ON子句、HAVING子句条件表达式的化简(尤其是对含有常量的表达式的化简、等式合并),优化没有GROUPBY子句情况下的COUNT(*)、MIN()、MAX(),裁剪分区partition(如果查询的表是分区表),确定多表的连接路径(单表是多表的特例,统计join的代价,两种多表连接算法选其一搜索最优的join顺序、生成执行计划)、优化等式谓词、优化DISTINCT、创建临时表存储临时结果优化分组排序等操作。在这样的过程中,MySQL没有把优化过程明显地分为逻辑查询优化阶段和物理查询优化阶段,而是互为混杂,在物理查询优化之后,继续进行了部分逻辑查询优化。这是MySQL查询优化器的一大特点。
MySQL查询优化器为SQL查询语句求解最优的执行方式。MySQL查询优化器架构和执行过程如下图所示。
MSQL查询语句的执行主要历经4个过程,分别如下:
MySQL查询语句的执行,主要历经以下4个模块。
实现MySQL查询优化器功能的主要是M3模块,其主要有以下两个子阶段的工作。
MySQL整个查询优化器从代码层面看,逻辑结构不是很清晰,但是从技术层面看,还是能够分为两个阶段,一是逻辑查询优化阶段,二是物理查询优化阶段。
MySQL的查询优化技术的实现,基本也可以分为逻辑优化和物理优化两个阶段,只是和PostgreSQL相比,界线没有那么清晰。MySQL的查询优化过程概述如下:
书籍: <<数据库查询优化的艺术: 原理解析和SQL性能优化>>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。