PostgreSQL查询引擎源码技术探析

来源:互联网 发布:知行理工app最新版 编辑:程序博客网 时间:2024/06/06 07:48


概述

PostgreSQL作为关系数据库中学院派的代表,其由UC.Berkeley完成,postgreSQL代码具有简洁,结构清晰,浓重的学院派气息。虽然其在国内的使用并未像MySQL广泛的在互联网公司内部使用,但随着国内大家慢慢的对于PostgreSQL的认识,越来越多的公司慢慢的采用PostgreSQL作为其基础架构,更有很多公司在PostgreSQL基础上进行二次开发来完成自己的需求,例如:AsterData产品,GreenPlum产品等均是基于PostgreSQL基础之上进行架构来实现MPP应用,以及Alibaba云计算采用PostgreSQL作为构建RDB的基础构建。

作为数据库内核中的重要一环,查询引擎在数据库中处于“大脑“作用,一个查询语句是否是以最优的方式来执行,该数据库是否高效率的运行均与查询引擎有着密不可分的联系;不同的数据库对于同一条查询语句执行时间各不相同,有快有慢。除去存储引擎之间的差别外,不同查询引擎所生成的查询计划和执行计划的优劣直接影响数据库在对同一条查询所表现出的性能高低。例如:对于查询语句中的join,不同的查询引擎所产生的优化策略导致的执行时间可能相差数倍;

作为学院派的代表PostgreSQL有着一套复杂的查询优化策略,例如对于子链接的处理,基于代价的优化策略,基于规则的查询优化等等策略。对于这些策略,PostgreSQL系统给出了开放的接口,使得用户可以灵活的使用适用于特定应用场景的自有优化策略。例如:pg_rewrite中所描述的基于查询语法树的改写(Rewrite)规则,又如pg_rules等等。作为连接服务器层与存储引擎层的中间层,查询引擎将用户发送来的SQL语句按照gramm.y中预先定义的SQL语法规则生成系统内部所使用的查询语法树形式(Abstract Syntax Tree, AST),而后查询引擎会将该查询语法树进行预处理---将其转换为查询引擎可处理的形式---查询树的形式,Query。

在由语法树到查询树的转换过程中,会将查询语句中的某些部分进行转换,例如:* 将会转换为被扩展为想对应关系表的所以列。在转换的过程中,查询引擎会根据语法树所标示的不同的类型来分别处理,例如:对应select类型的语句,update类型的语句,create类型的语句等。具体可以参考我的其它两篇文章:

[1]语法树生成@http://www.leehao.org/index.php/2015/11/10/how-postgresql-knows-what-i-want-to-do/

[2]语法树到查询树的转换@ http://www.leehao.org/index.php/2015/11/10/how-pg-knows-what-i-want-to-do-2/

在查询引擎语法树到查询树转换后,PostgreSQL查询引擎会使用pg_rewrite中所设定的转换规则进行所谓的基于规则的转换,例如:对于view,PostgreSQL查询引擎会将其进行转换,为后续的优化提供可能。

在完成了基于规则的优化后,PostgreSQL查询引擎进入到,我们称之为逻辑优化的阶段。在该阶段中PostgreSQL查询引擎,完成对于公共表达式的优化,子链接的上提以及优化等,例如:对于Join/In/Not In等优化处理(进行semi-join, anti-semi-join处理等等)。经过此阶段的优化后,所得到的查询树为一颗遵循了先选择后投影规则的最优查询树。

在完成了对于查询树的优化处理后,PostgreSQL查询引擎接下来要做另外一件非常重要的事情---执行计划的生成。PostgreSQL查询引擎会依据查询树,通过遍历该查询树,来生成相应的执行计划,在执行计划的生成过程中,PostgresQL查询引擎会选择一条最优的执行路径来进行执行。例如:对于多表的join操作,不同的join顺序所产生的效果各不同,而这直接导致了中间元组的大小;同时,对于关系表上是否建有索引,并根据该索引信息,采用不同的表扫描方式也会极大的影响到执行效率。通常,我们依据Cost = cpu_cost + io_cost 公式来选择一条最优的执行路径,其中,cpu_cost表明执行该条执行计划所需要的cpu代价,IO_cost则为相应的io代价。

l  逻辑优化

当PostgreSQL在接收用户的SQL查询语句后,在完成了对于该查询语句的词法分析和语法分析后(工作是根据语法树上节点的类型分别完成对于insert,delete,update,select等子句的分析,例如:将*号转为为确切的列等等。此项工作由函数parse_analyze来完成,backend/parse/analyze.c),并完成对于原始语法树的改写(rewritephrase)工作后(改写的主要使用pg_rewrite,pg_rulesd等系统表中所提供的重写规则对原始的语法树进行重写操作;此项工作由pg_rewrite_query函数来完成,backend/tcop/postgres.c)。在完成上述的操作后,PostgreSQL会将原始的Node类型语法树转为Query类型的查询树并以此为基础对该查询树进行等价变化(即:逻辑优化),形式最优的查询树。经过优化的查询树是我们查询计划和执行计划的基础。

具体详细解析见后续:http://www.leehao.org/index.php/2015/11/09/pgoptimization/


1 0
原创粉丝点击