一条 Select 语句 在 Postgresql 中的执行链路
本文只是逻辑上的概览,并没有太过深入的设计细节的描述,对应的postgresql 的代码版本是
REL_12_2
1. DML 语句入口
如何搭建 gdb 调试pg 源代码环境,可以参考:利用GDB 快速阅读 postgresql 内核源代码
- 启动pg 数据库:
./bin/pg_ctl -D /home/zhg/pgsql/pgsql/data -l logfile restart
- 启动 psql,
./bin/psql testdb
testdb 是我已经创建好的数据库,且已经创建好了一个测试表 - 重开一个新的终端,
gdb attach -p pid
参考 上文链接,需要连接到 [local] idle 进程,并设置好源码目录 - 在psql 终端输入 查询语句
select * from a;
,此时即可在 gdb 终端进行调试。
刚进入之后整个 pg 的函数栈如下,主要是利用epoll 来处理 客户端的链接。
2. 执行链路
在主进程的 PostgresMain
函数中处理来自 psql 交互终端的请求(此时还没有办法确认是一个查询请求):
gdb 不断得next执行,最终会通过 exec_simple_query(query_string)
函数进入输入命令的处理阶段。
进入之后的主要的执行步骤 以及其对应的函数 有如下几个:
start_xact_command
开启事务,写入事务标记,创建快照并入栈。pg_parse_query
根据输入的 命令字符串 进行 SQL 词法和语法解析,主要目的是解析出DML 命令(一个输入可能有多个 DML 命令),最后以链表的形式返回解析结果。实现代码是在src/backend/parser/gram.y
中。接下来都是在链表内部 循环执行每一个指令
利用gdb 我们能够很清晰得看到 parsetree_list 中的内容,可以看到在我们输入的select * from a;
这个语句中,解析出来的链表长度只有1,也就是只有一个 DML 指令,同时指令的 statement 内容是T_SelectStmt
类型。
创建快照 并入栈
PushActiveSnapshot
(解析+优化时需要创建快照),在pg_analyze_and_rewrite():
解析器会生成执行计划(优化器的逻辑都在里面):
pg_plan_queries
,移除快照PopActiveSnapshot
。最终 优化器会对 DML 语句生成执行计划。执行器的 执行逻辑部分:
CreatePortal()
-->PortalDefineQuery()
-->PortalStart()
-->PortalSetResultFormat()
-->PortalRun()
-->PortalDrop()
基本链路如下图:finish_xact_command()
提交事务,主要是 commit部分,会写wal (redo类型 的一种持久化文件,因为 DML 是 select 语句,其实不需要,这里的链路主要是在 inert/update 时会写 WAL)。
3. 执行器的详细逻辑
这里着重主要介绍 上文中的第六步,也就是执行器的逻辑。
执行器的入口通过 Portal 展开,主要的几个变量如下:
- Portal : 表示可以执行的 或者 正在执行的状态信息,包括前面优化器生成的执行计划。
- Estate : 保存执行器的工作状态
- TupleTableSlot : 保存元组数据的 数据结构。
执行器的大体逻辑包括:
CreatePortal
, 创建 Portal 变量(构造 Portal 变量),作为执行计划的载体PortalStart
, 初始化DML 对应DML 语句在底层存储引擎侧的执行逻辑,比如select * from table;
对应的 Portal 策略是PORTAL_ONE_SELECT
,其底层默认是 heap表引擎,会将heap 表引擎底层的执行 查找逻辑的函数交给 Portal 变量内部的 PlanState 的一个 函数指成员。PortalRun
,执行计划,底层存储引擎的数据读取会通过上一步初始化好的函数进行。PortalDrop
,执行完成,清理对应执行过程中pin主的资源,以及触发一些插件的执行逻辑。
这主要的几个入口逻辑 以及后续的执行链路基本如下:
在后续我们靠近存储引擎侧的入口部分,比如在PortalStart
调用栈中,因为我们的执行计划 Plan 在 select * from table;
这个语句下的 类型是 T_SeqScan
gdb能够看到,Plan
的类型
这个时候会根据 Plan 的类型来选择对应的执行函数,如下图,根据 T_SeqScan
选择了 ExecInitSeqScan
。
将选择好的具体执行DML的函数 赋值给 PlanState 中ExecProcNode
回调函数变量,其他的DML 语句生成的执行计划的执行类型 也会根据类型初始化为各自的 ExecProcNode
4. 总结
从代码层面来看 sql 语句的执行链路,能够完整看到一条语句如何 被pg 解析,经过优化器 到达执行器,在执行器内部通过什么样的方式去和底层的 heap 引擎进行交互。
以上的代码执行逻辑同样适用于 其他的 DML 语句(INSERT, UPDATE, DELETE等),只是底层生成执行计划时的引擎访问函数就有差异了。
当然,这个DML 语句的执行链路都是在 PG 的 主逻辑中,但是 postgres 进程还会有一些非常重要的子进程:
checkpointer
,写heap 表引擎的时候只是将 insert语句 插入的数据,生成了可以写入的 heap tuple放在内存中的 buffer中,后续落盘会通过 checkpointer 进行落盘。(数据的ACD 特性是通过 REDO log 保证的,前面 第二节主体执行链路中提到的start_xact_command
和finish_xact_command
中的redo 写入的逻辑)。autovacuum
主要是用来进行 GC heap表引擎 支持MVCC 引入的多版本,当然还有一些索引 之类的多版本清理。logical replication
用来做 主从复制的。walwriter
专门负责 调度写 前面说到的 redo log 的。stats collector
,采集pg 内部的 stats 信息。
一条 Select 语句 在 Postgresql 中的执行链路相关推荐
- 一文搞懂select语句在MySQL中的执行流程!
MySQL作为互联网行业使用最多的关系型数据库之一,与其免费.开源的特性是密不可分的.然而,很多小伙伴工作了很多年,只知道使用MySQL进行CRUD操作,这也导致很多小伙伴工作多年后,想跳槽进入大厂, ...
- 一条sql语句在mysql中如何执行的
文心阁小说本篇文章会分析下一个 sql 语句在 MySQL 中的执行流程,包括 sql 的查询在 MySQL 内部会怎么流转,sql 语句的更新是怎么完成的. 在分析之前我会先带着你看看 MySQL ...
- 原来select语句在MySQL中是这样执行的!看完又涨见识了!这回我要碾压面试官!
大家好,我是冰河~~ MySQL作为互联网行业使用最多的关系型数据库之一,与其免费.开源的特性是密不可分的.然而,很多小伙伴工作了很多年,只知道使用MySQL进行CRUD操作,这也导致很多小伙伴工作多 ...
- 用一条sql语句删除表中所相同记录
用一条sql语句删除表中所相同记录如下一.具有主键的情况 a.具有唯一性的字段id(为唯一主键) delete table where id not in ( select max(id) from ...
- 一条SQL语句在MySQL中是如何执行的
来源:http://t.cn/E6U9Z9T 概览 本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的更新是怎么完成的. 一.mysql架 ...
- 一条SQL语句查询数据库中的所有表、存储过程、触发器
一条SQL语句查询数据库中的所有表.存储过程.触发器 (sysobjects表信息) 该条语句查询返回所有的用户表 select * from sysobjects where xtype='u' ...
- MySQL实战 | 01 当执行一条 select 语句时,MySQL 到底做了啥?
原文链接:当执行一条 select 语句时,MySQL 到底做了啥? 也许,你也跟我一样,在遇到数据库问题时,总时茫然失措,想重启解决问题,又怕导致数据丢失,更怕重启失败,影响业务. 就算重启成功了, ...
- PostgreSQL中的执行计划
PostgreSQL中的执行计划 EXPLAN 预生成执行计划 EXPLAN sql 真实执行计划 explan analyze sql 输出详细内容 explan(analyze on, timin ...
- mysql中,一条select语句是如何执行的?
接下来通过语句弄明白整个Select语句的内部运行状态: 连接器: Mysql>mysql -uroot -p 你首先连接到这个数据库上:链接器负责跟客户端建立连接,获取权限,维持和管理连接 ● ...
最新文章
- 我的第一份工作是个小公司
- Eclipse开发struts完全指南
- 曙光计算机系统,曙光1000大规模并行计算机系统
- 2010.9.29 今日问题
- Spring中BeanPostProcessor
- 电脑 你离我有多远!
- java中下拉框select和单选按钮的回显操作
- 【图像去噪】基于matlab中值+均值+高斯+Laplacian+Sobel+Prewitt图像去噪【含Matlab源码 025期】
- 解决Android studio在虚拟机上可以正常运行,而在手机上闪退的问题
- 淘宝手淘搜索怎么做?大神导航,一个神奇的网站,从此开启大神之路!
- 产品需求文档模板,不用找了(附“简”例)【转】
- MFC制作的入坑级别管理系统
- 计数排序CountingSort
- C/C++中的逻辑右移和算术右移
- 全球响应,维谛技术(Vertiv)助力EPC企业出海“加速度”
- 红帽Linux重置root密码
- 为什么需要稀疏编码及解释
- 【全网最全最细】青龙面板搭配Ninja+依赖+Ninja配置的超细讲解教程!!!
- 移动技术开创互联网奇迹
- Bash shell语言学习
热门文章
- wordpress企业网站主题仿制02-wordpress企业网站首页的仿制
- linux sh文件格式,SH文件扩展名 - 什么是.sh以及如何打开? - ReviverSoft
- win如何卸载cuda8
- Node.js v0.10.31API手册-Addons插件
- 超鸿蒙混希夷的翻译,对《愚溪诗序》一处译文的思考
- Sql Server利器sql prompt
- The Shawshank Redemption-2
- RHCS基本理論(台湾人写的不错的文章)
- Mobius反演学习
- Excel导出模板加数据时,下拉框丢失解决方案