Append
Append
遍历各子计划并合并其输出行。
当前查看 PostgreSQL 18.6。
说明
遍历各子计划并合并其输出行。
- 核心节点标签
- T_Append
- 结构化 EXPLAIN 节点类型
- Append
- 输入
- 多个子计划
- 输出
- 合并后的元组
- 执行器初始化函数
- ExecInitAppend
- 内存机制
- unclassified
EXPLAIN 名称与属性
结构化格式使用上述 Node Type。文本格式名称还可能包含操作、策略、连接类型、扫描方向或聚合阶段属性。
此源码记录的文本名称:Append.
并行感知与并行安全是不同的计划属性。在并行工作进程内运行的节点不一定是并行感知节点。
内存与临时存储
本次抽取不为此节点设定统一的内存上限或落盘策略。请查看同一构建的实现、相关表达式或提供方。
并行执行与运行信息采集
以下源码回调可以协调执行或收集工作进程的测量数据。回调存在不代表该节点普遍支持共享并行扫描或共享状态。
此构建的回调:ExecAppendEstimate, ExecAppendInitializeDSM, ExecAppendInitializeWorker, ExecAppendReInitializeDSM.
同版本手册说明
通常 EXPLAIN 显示规划器创建的每个节点。但执行器有时可以根据规划阶段尚不可知的参数值,判定某些节点无法产生任何行,因此不必执行。(目前仅会发生在扫描分区表的 Append 或 MergeAppend 节点的子节点上。)此时 EXPLAIN 省略这些节点,改为显示 Subplans Removed: N。
每当 PostgreSQL 需要将来自多个源的行合并成一个结果集时,它就会使用 Append 或 MergeAppend 计划节点。这种情况常见于实现 UNION ALL 或扫描分区表时。这样的节点和其他任何计划中的情形一样,也可以用于并行计划。不过,在并行计划中,规划器也可能改用 Parallel Append 节点。
当 Append 节点用于并行计划时,每个进程都会按照子计划出现的顺序执行它们,因此所有参与进程会协作执行第一个子计划直到其完成,然后再大致同时转向第二个子计划。而当使用 Parallel Append 时,执行器会尽可能均匀地将参与进程分散到各个子计划上,从而使多个子计划能够同时执行。这样既避免了争用,也避免让那些从未执行某个子计划的进程承担其启动代价。
此外,与在并行计划中只能包含部分子计划的普通 Append 节点不同,Parallel Append 节点既可包含部分子计划,也可包含非部分子计划。非部分子计划只由一个进程扫描,因为多次扫描会产生重复结果。因此,即使没有高效的部分计划,拼接多个结果集的计划也能实现粗粒度并行。例如,针对分区表的查询,可能只有借助不支持并行扫描的索引才能高效执行。规划器可能选择使用 Parallel Append 拼接多个普通 Index Scan 计划;每次索引扫描都必须由单个进程完整执行,但不同扫描可以由不同进程同时执行。
本版手册中的示例
示例摘自 PostgreSQL 18.6 手册;本百科未实际执行此示例。
当 UPDATE 、 DELETE 或 MERGE 命令影响分区表或继承层次时,输出可能像这样:
EXPLAIN UPDATE gtest_parent SET f1 = CURRENT_DATE WHERE f2 = 101;
QUERY PLAN
----------------------------------------------------------------------------------------
Update on gtest_parent (cost=0.00..3.06 rows=0 width=0)
Update on gtest_child gtest_parent_1
Update on gtest_child2 gtest_parent_2
Update on gtest_child3 gtest_parent_3
-> Append (cost=0.00..3.06 rows=3 width=14)
-> Seq Scan on gtest_child gtest_parent_1 (cost=0.00..1.01 rows=1 width=14)
Filter: (f2 = 101)
-> Seq Scan on gtest_child2 gtest_parent_2 (cost=0.00..1.01 rows=1 width=14)
Filter: (f2 = 101)
-> Seq Scan on gtest_child3 gtest_parent_3 (cost=0.00..1.01 rows=1 width=14)
Filter: (f2 = 101)执行器实现说明
说明:每个 Append 节点包含一个或多个必须逐一处理的子计划,方向可以正向或反向。执行第 whichplan 个子计划取回元组,直到它不再返回元组,然后关闭该计划并启动下一个。
Append 节点不使用左、右子树,而是维护一个子计划列表,因此典型的 Append 节点在计划树中如下所示:
... / Append -------+------+------+--- nil / \ | | | nil nil ... ... ... subplans
Append 节点目前用于并集操作,也用于需要扫描多个关系的继承查询。例如,在标准的 person/student/employee/student-emp 示例中,student 和 employee 继承自 person,而 student-emp 同时继承自 student 和 employee,查询如下:
| Append -------+-------+--------+--------+ / \ | | | | nil nil Scan Scan Scan Scan | | | | person employee student student-emp
核心源码中的 EXPLAIN 标识
case T_Append:
pname = sname = "Append";
break;本构建中的 EXPLAIN 标签
| 文本格式标签 | 结构化节点标识 |
|---|---|
| Append | Append |
相关条目
文档与源码
- src/backend/commands/explain.c:1406
- src/backend/executor/execProcnode.c:181
- src/backend/executor/nodeAppend.c
- src/include/nodes/plannodes.h
- PostgreSQL 18.6 · using-explain
- PostgreSQL 18.6 · parallel-plans
- PostgreSQL 18.6 · using-explain
来源构建
- 版本
- 18.6
- 构建
- PostgreSQL 18.6 source archive
- 来源指纹
555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f
版本比较
PostgreSQL 10 → 11: 属性变化。
以下差异保留原始字段名与英文源描述。
--- PostgreSQL 10
+++ PostgreSQL 11
@@ -2,7 +2,12 @@
"initializer": "ExecInitAppend",
"memory_mechanism": "unclassified",
"node_tag": "T_Append",
- "parallel_callbacks": [],
+ "parallel_callbacks": [
+ "ExecAppendEstimate",
+ "ExecAppendInitializeDSM",
+ "ExecAppendInitializeWorker",
+ "ExecAppendReInitializeDSM"
+ ],
"partial_modes": [],
"strategies": [],
"text_names": [
比较已记录的接口与属性,排除来源指纹和构建元数据。某个样本中没有记录,不能据此判断实际引入或移除的版本。
相关条目
Merge AppendMergeAppendRecursive UnionRecursiveUnionSetOpSetOpUniqueUnique
导出 JSON · 返回执行计划节点 · 收录范围为 PostgreSQL 10 至 20;最早采样版本不一定是实际引入版本。