1. 走进PG,查询SQL执行流程

2022-02-26 11:56:54 浏览数 (1)

PostgreSQL作为传统关系型数据,在设计架构上和Oracle非常相似,下图可以带给你直观的了解。

核心进程:

postgres: logger 负责写日志相关进程

postgres: checkpointer checkpoint进程

postgres: background writer 刷数据进程

postgres: walwriter WAL日志进程

postgres: autovacuum launcher vacuum launcher 进程

postgres: stats collector 统计信息进程

postgres: logical replication launcher 逻辑复制launcher进程

  • WAL sender process (if Streaming Replication is active)
  • WAL receiver process (if Streaming Replication is active)

从描述上可以看出,PostgreSQL是进程模型,尤其要注意每一个客户端连接对应一个后台进程,这也就意味着‘连接’在PostgreSQL里面是非常重要的资源,在之后有会专题来聊连接的问题。

看到这里会有一个疑问,没有连接管理进程,谁来负责建立连接呢? 答案是postgres主进程负责连接的建立和释放,一个肉眼可见的瓶颈点吧?

回到正题,一条查询SQL是怎么执行的呢?

客户端要和数据库建立通信,需要经过连接器,它收到建立连接请求后,postgres主进程会fork出一个子进程来完成SQL执行操作,由客户端发起的SQL经过解析器-->优化器-->执行器等阶段后返回查询结果到客户端。

连接器

PostgreSQL通过postmaster进程监控建立连接请求,核心逻辑是通过fork子进程方式创建连接,创建连接时会做一系列初始化操作,其中InitPostmasterChild中通过宏控制是否启用setsid,建立完连接后进入ClientAuthentication,认证步骤第一步是进行账号来源客户端IP、认证方法检查,以此来决定使用何种方式认证。接下来看一个HBA报错:

HBA配置由$DATADIR/pg_hba.conf文件内容控制,配置好账号访问策略后,以md5认证方式访问数据库,输入密码后,可以愉快的玩耍了。

解析器

解析器会对SQL做语法解析,生成解析树,一个SQL写法不对会直接返回错误。细节可以参考pg_parse_query。

优化器

拿到解析树之后,经过pg_analyze_and_rewrite会对SQL进行分析和重写,在分析阶段会对SQL语义判断,比如列存不存在、有没有跨DB查询、表的别名用的对不对都会在这个阶段做判断,列名不存在SQL错误:

groupby列和查询列不一致报错:

通过重重检查之后,数据库会生成最优的‘执行规划’,它指明SQL应该按照什么样的路径执行。走全表扫描还是用索引,用A索引还是B索引,内部有一套成本估算的方法来评估。

做过Oracle的朋友一定熟悉硬解析、软解析、软软解析,那PostgreSQL的机制是什么呢?

PG12引入plan_cache_mode参数,可以控制解析策略,灵活调整查询计划查询对SQL的影响。

执行器

在SQL真正执行之前,还需要对查询计划做初始化和预检查,主要内部在InitPlan部分,初始化查询计划包括打开文件、访问存储、启动规则管理、权限检查等。常见的权限错误问题如下:

经过上面的步骤,执行器会返回存储上满足条件的数据。

看到这里相信对PostgreSQL内部执行流程有了整体了解,那么下面的SQL会报错吗?

前提:id1是主键、id2和c1是普通列。

select c1,count(*) from t10 where id2=55 group by id1;

0 人点赞