获得技术资料内容,请访问Greenplum中文社区网站
继上次分享的《深入剖析查询优化技术内幕之概述篇》之后,今天继续和大家分享关于查询树部分的内容。
《PostgreSQL技术内幕-查询优化深度探索》揭示了PostgreSQL数据库中查询优化的实现技术细节,先是对子查询提升、外连接消除、表达式预处理、谓词下推、连接顺序交换、等价类推理等逻辑优化方法进行了详细的描述,而后又结合统计信息、选择率、代价对扫描路径创建、路径搜索方法、连接路径的建立、Non-SPJ路径的建立、执行计划的简化与生成等进行了深度的探索,从而使读者可以对PostgreSQL数据库的查询优化器有深层次的了解。
这本书适合于从事数据库内核开发人员及相关领域的研究人员、数据库DBA、高等院校相关专业的本科生或者研究生阅读。
查询树
一个SQL查询语句在经过了词法分析、语法分析和语义分析之后会形成一棵查询树,这棵查询树实际上就对应了一个关系代数表达式,它是查询优化器的输入,贯穿了查询优化的整个过程。所谓“工欲善其事,必先利其器”,在开始对查询优化器的代码进行分析之前,对查询树必须要有一定的了解,下面就开始分析查询树的结构,同时也介绍一下查询树涉及的其他的数据结构。
Node的结构
PostgreSQL数据库中的结构体采用了统一的形式,它们都是基于Node结构体进行的“扩展”,Node结构体中只包含一个NodeTag成员变量,NodeTag是enum(枚举)类型。
其他的结构体则利用C语言的特性对Node结构体进行扩展,所有结构体的第一个成员变量也是NodeTag枚举类型,例如在List结构体里,第一个成员变量是NodeTag,它可能的值是T_List、T_intList或者T_OidList,这样就能分别指代不同类型的List。
而Query结构体也是以NodeTag枚举类型作为第一个变量,它的取值为T_Query。
这样无论是List结构体的指针,还是Query结构体的指针,我们都能通过Node结构体的指针(Node*)来表示,而在使用对应的结构体时,则通过查看Node类型的指针中的NodeTag枚举类型就可以区分出该Node指针所代表的结构体的实际类型。
Var结构体
Var结构体表示查询中涉及的表的列属性,在SQL语句中,投影的列属性、约束条件中的列属性都是通过Var来表示的,在语法分析阶段会将列属性用ColumnRef结构体来表示,在语义分析阶段会将语法树中的ColumnRef替换成Var用来表示一个列属性。下面来看一下Var结构体中各个变量的具体含义。
varno:用来确定列属性所在的表的“编号”,这个编号源自Query(查询树)中的rtable成员变量,查询语句中涉及的每个表都会记录在rtable中,而其在rtable中的“编号”(也就是处于链表的第几个,从1开始计数,这个编号用rtindex表示)是唯一确定的值,在逻辑优化、物理优化的过程中可能varno都是rindex,而在生成执行计划的阶段,它可能不再代表rtable中的编号,这在第10章中会进行介绍。
varattno/vartype/vartypmod:varattno确定了这个列属性是表中的第几列,vartype和vartypmod则和列属性的类型有关。在创建表的时候,PostgreSQL数据库会按照SQL语句中指定的列的顺序给列属性编号,并将编号记录在PG_ATTRIBUTES系统表中,同时会将