前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Postgresql源码(61)查询执行——最外层Portal模块

Postgresql源码(61)查询执行——最外层Portal模块

作者头像
mingjie
发布2022-07-14 13:50:49
4080
发布2022-07-14 13:50:49
举报

相关 《Postgresql源码(61)查询执行——最外层Portal模块》 《Postgresql源码(62)查询执行——子模块ProcessUtility》

1 背景

  • 本篇介绍查询执行最外面一层:portal模块。部分摘自《PostgreSQL数据库内核分析》。
  • 按照最近读代码的线索,后面几篇侧重分析下查询执行的架子,下一篇ProcessUtility。
  • 查询执行在查询编译后面执行,负责执行具体的SQL 或 按前一阶段生成的计划来执行具体的PLAN。

PG14中截取部分SQL语法:https://www.postgresql.org/docs/14/sql-commands.html

代码语言:javascript
复制
ABORT — abort the current transaction
...
ALTER INDEX — change the definition of an index
...
ALTER TABLE — change the definition of a table
ALTER TABLESPACE — change the definition of a tablespace
...
BEGIN — start a transaction block
CALL — invoke a procedure
CHECKPOINT — force a write-ahead log checkpoint
CLOSE — close a cursor
...
CREATE FOREIGN DATA WRAPPER — define a new foreign-data wrapper
CREATE FOREIGN TABLE — define a new foreign table
CREATE FUNCTION — define a new function
...
CREATE TABLE — define a new table
CREATE TABLE AS — define a new table from the results of a query
CREATE TABLESPACE — define a new tablespace
...
DELETE — delete rows of a table
...
EXPLAIN — show the execution plan of a statement
...
REVOKE — remove access privileges
...
VACUUM — garbage-collect and optionally analyze a database
...

大致看过可以发现:

  • 大部分SQL语句如创建表、启动事务等,会提供单一的、具体的某个功能点,这类功能无法被优化器优化,执行过程固定,不会有变化;
  • 另外一类SQL如增删改查,这类SQL可以被优化器优化,定制执行计划,执行过程会有不同,完全跟着执行计划来。

如果我们自己来设计这个系统,应该也会把SQL执行分成两类,带执行计划的DML(增删改查)不带执行计划的DDL。

2 查询执行整体

PG中的SQL在经过语法解析、查询编译后,进入执行模块,整形模块的分三个子模块:

  • 入口:portal子模块(下图蓝色)
  • 处理DML的Executor子模块(下图绿色)
  • 处理DDL的ProcessUtility子模块(下图橙色)

SQL会在查询编译阶段得到plantree_list,在portal模块启动时(函数PortalStart),根据plantree_list中具体情况(函数ChoosePortalStrategy),来决定PortalStrategy的值,后面执行根据PortalStrategy来决定进入Executor还是ProcessUtility。

3 portal工作流程

3.1 portal关键数据结构

一、portal状态

代码语言:javascript
复制
typedef enum PortalStatus
{
	PORTAL_NEW,					/* freshly created */
	PORTAL_DEFINED,				/* PortalDefineQuery done */
	PORTAL_READY,				/* PortalStart complete, can run it */
	PORTAL_ACTIVE,				/* portal is running (can't delete it) */
	PORTAL_DONE,				/* portal is finished (don't re-run it) */
	PORTAL_FAILED				/* portal got error (can't re-run it) */
} PortalStatus;

二、portal结构

关键变量:

  • 【0】SQL语句
  • 【1】注意:执行计划树链表
  • 【2】根绝策略决定走Executor还是ProcessUtility
  • 【3】当前portal状态
  • 【4】Executor执行需要的查询描述符
  • 【5】描述返回的元组结构
代码语言:javascript
复制
typedef struct PortalData
{
	/* Bookkeeping data */
	const char *name;			/* portal's name */
	const char *prepStmtName;	/* source prepared statement (NULL if none) */
	MemoryContext portalContext;	/* subsidiary memory for portal */
    ...

// 【0】SQL语句
	const char *sourceText;		/* text of query (as of 8.4, never NULL) */
	CommandTag	commandTag;		/* command tag for original query */
	QueryCompletion qc;			/* command completion data for executed query */
	
// 【1】注意:执行计划树链表
	List	   *stmts;			/* list of PlannedStmts */
	CachedPlan *cplan;			/* CachedPlan, if stmts are from one */

	ParamListInfo portalParams; /* params to pass to query */
	QueryEnvironment *queryEnv; /* environment for query */

// 【2】根绝策略决定走Executor还是ProcessUtility
	PortalStrategy strategy;	/* see above */
	int			cursorOptions;	/* DECLARE CURSOR option bits */
	bool		run_once;		/* portal will only be run once */

// 【3】当前portal状态
	PortalStatus status;		/* see above */
    ...

// 【4】Executor执行需要的查询描述符
	QueryDesc  *queryDesc;		/* info needed for executor invocation */

// 【5】描述返回的元组结构
	TupleDesc	tupDesc;		/* descriptor for result tuples */
	/* and these are the format codes to use for the columns: */
	int16	   *formats;		/* a format code for each column */
    ...
}			PortalData;

from 《PostgreSQL数据库内核分析》

3.2 portal执行流程

简版:

代码语言:javascript
复制
exec_simple_query
  |
  PortalStart
  |
  PortalRun
  |
  PortalDrop
PortalStart

执行一些初始化工作,比如

  1. 选择执行策略:ChoosePortalStrategy
  2. 如果要走Executor了,就先执行下ExecutorStart初始化Executor。
代码语言:javascript
复制
PortalStart
  portal->strategy = ChoosePortalStrategy(portal->stmts)
  switch (portal->strategy)
  {
    case PORTAL_ONE_SELECT:
      // 拿快照
      PushActiveSnapshot
      // 创建查询描述符
      CreateQueryDesc
      // 初始化Executor
      ExecutorStart
      
    case PORTAL_ONE_RETURNING:
    case PORTAL_ONE_MOD_WITH:
      PortalGetPrimaryStmt
      ExecCleanTypeFromTL
      
    case PORTAL_UTIL_SELECT:
      PortalGetPrimaryStmt
      UtilityTupleDescriptor
      
    case PORTAL_MULTI_QUERY:
      portal->tupDesc = NULL
  }
  portal->status = PORTAL_READY;

其中执行策略的选择ChoosePortalStrategy:

PortalRun

PortalRun是一级portal执行函数,负责分发给二级portal执行函数

代码语言:javascript
复制
PortalRun
  switch (portal->strategy)
    case PORTAL_ONE_SELECT:
    case PORTAL_ONE_RETURNING:
    case PORTAL_ONE_MOD_WITH:
    case PORTAL_UTIL_SELECT:
      PortalRunSelect
    
    case PORTAL_MULTI_QUERY:
      PortalRunMulti 

PortalRun二级执行函数有四个,其中两个从PortalRun调入

代码语言:javascript
复制
PortalRunSelect     <-- PortalRun
PortalRunMulti      <-- PortalRun

PortalRun三级执行函数有两个,从PortalRunMulti调入

代码语言:javascript
复制
PortalRunUtility    <-- PortalRunMulti
PortalRunFetch      <-- (游标专用)从SPI系统_SPI_cursor_operation 
                    <-- 或 standard_ProcessUtility的PerformPortalFetch 调入

执行过程:

PortalDrop

清理

代码语言:javascript
复制
PortalDrop
  PortalHashTableDelete
  PortalReleaseCachedPlan
  ResourceOwnerRelease
  ...
  MemoryContextDelete(portal->portalContext)
  pfree(portal)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 背景
  • 2 查询执行整体
  • 3 portal工作流程
    • 3.1 portal关键数据结构
      • 3.2 portal执行流程
        • PortalStart
        • PortalRun
        • PortalDrop
    相关产品与服务
    云数据库 PostgreSQL
    腾讯云数据库 PostgreSQL(TencentDB for PostgreSQL,云 API 使用 postgres 作为简称)能够让您在云端轻松设置、操作和扩展目前功能最强大的开源数据库 PostgreSQL。腾讯云将负责绝大部分处理复杂而耗时的管理工作,如 PostgreSQL 软件安装、存储管理、高可用复制、以及为灾难恢复而进行的数据备份,让您更专注于业务程序开发。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档