暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PgSQL技术内幕 - PostgreSQL查询处理阶段综述

yanzongshuaiDBA 2024-04-09
111
PgSQL技术内幕 - PostgreSQL查询处理阶段综述
查询发送到PgSQL后在后台进程会经历几个处理阶段,每个阶段都有不同职责,保证用户在尽可能短的时间内收到正确的响应。这个过程相当复杂,本文概述每个查询处理阶段的作用和意义。

5个查询处理阶段

解析器

PgSQL使用lexFlex lexical analyzer)和yaccbison parser)工具创建解析器。通常通过写一个正则表达式定义文件来完成,然后将其转换成响应的C文件。这些生成的源文件在src/backend/parser。当执行make编译源码时,自动转换。

摘要:
1)负责检查文字语法错误.
2)生成解析树。
3)使用flex bison 解析查询语法。
4)入口在parser/parser.c

分析器

主要目的是检查解析阶段创建的raw_parsetree结构。例如,检查表名、数据类型、字段名等是否有效。若他们存在,PG使用一个OID进行内部表示,并产生一个查询树。
1)负责更深入的语法分析
2)访问指定的数据库
3)检查指定的表是否存在
4)检查数据格式的正确性
5)将表名转换成内部的OID
6)产生查询树
7)入口在parse/analyze.c

重写

目的主要是重写和优化分析器产生的查询树。比如检查是否引用了其他视图或规则。如果是,则重写语句并将视图转换成对应的语句。为规划器输出一个优化的查询树。
1)如有需要,负责改写查询
2)如果查询访问了视图或者规则对象,根据视图或规则的定义进行扩展或重写
3)入口在rewrite/rewriteHandler.c

规划器

负责代价评估并且产生最佳执行计划。根据不同语句类型、表结构、是否存在索引及大小等计算不同的执行方法(路径)。每个路径都有一个评估代价,选择代价最小的路径作为最优查询计划。最后,产生最优查询计划(PlannedStmt结构)后将其发送给执行器模块去执行。
规划器相对复杂,大型函数的开发通常需要一定理解甚至改变规划器。
plancat.c中的函数get_relation_info()时代价评估重要函数,他会告诉规划器以下内容:
1)该表中有多少页
2)该表中有多少记录
3)该表有多少索引
4)索引键是哪一列
5)是否有外表
6)其他一些信息
这些是规划器进行代价评估的基础,通过以下访问方法获取:
1)Heap访问方法:获取数据表信息
2)索引访问方法:获取索引相关信息
总结:
1)负责制定执行计划。
2)找出所有可能的方法(或路径)
3)选择在最短时间内完成查询的最佳方法。
4)入口:optimizer/plan/planner.c

执行器

它干的活主要是执行规划器产生的执行计划。由portal模块控制。根据执行计划的性质要么执行executor,要么执行processUtility

1)根据执行计划去执行查询
2)访问PG后台进程的几个其他模块来完成该查询
3)入口executor/execMain.c

执行器之后发生什么

执行器模块会依赖其他模块完成查询比如访问方法层(表访问方法和索引访问方法)。访问方法层会读或写数据。同时,访问方法层也会依赖于其他模块,比如buffer管理和存储引擎,来处理真实数据的读和写:

查询处理的生命周期

源代码中查询处理开始于exec_simple_query()函数。该函数调用每个查询处理阶段提供的入口函数,最后返回DestReceiver对象。

Portal-DestReceiver

不管是Executor还是ProcessUtility,最后都会返回一个或多个结果。这些结果存储在TupleTableSlot中。Tuple可以理解成行记录。一个tuple中可以有多个值,对应于相应的列。PG当前仅支持Heap作为记录类型,也叫做HeapTupleHeap的行为由HeapAccessMethod定义。
DestReceiver结构中存储了TTS,该结构告诉了Portal模块将结果在哪里显示。

原文

https://www.highgo.ca/2024/01/26/a-comprehensive-overview-of-postgresql-query-processing-stages/

文章转载自yanzongshuaiDBA,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论