{"Entry":{"collection":"plan","key":"group","name":"Group","aliases":["Group","T_Group"],"metadata":{"aliases":["Group","T_Group"],"category":"Aggregation","content_hash":"416e3ab8f1dcba42ca83b9d6d8d13107ea763e26250afcd2b26631c28618622f","derived_content_hash":"9826c7c815aa16445970300bc9dd87aebcb82a10715d2cd325180b6d22d2405c","imported_at":"2026-09-30T00:40:44.001041+08:00","name":"Group","name_zh":"Group","slug":"group","summary":"Groups an ordered input stream by its grouping columns."}},"Definition":{"Collection":"plan","Key":"group","SourceDatabase":"center","Version":"18","SourceTable":"plan_node","SourceKey":"group","SourceRevision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","Facts":{"comparison_data":{"initializer":"ExecInitGroup","memory_mechanism":"unclassified","node_tag":"T_Group","parallel_callbacks":[],"partial_modes":[],"strategies":[],"text_names":["Group"]},"comparison_hash":"c75b880801aecfa8f510650c6bb3c2e0aa820810550fefe9c62d04727c0c0048","description":["Groups an ordered input stream by its grouping columns."],"description_zh":"按分组列对有序输入分组。","description_zh_html":"\u003cp\u003e按分组列对有序输入分组。\u003c/p\u003e\u003cp\u003e核心节点标识：\u003ccode\u003eT_Group\u003c/code\u003e；EXPLAIN 名称：\u003ccode\u003eGroup\u003c/code\u003e。\u003c/p\u003e\u003cp\u003e本版本源码中的并行执行或观测回调：该节点实现中未提取到此类回调。回调的存在不表示该节点必然支持共享并行扫描；在并行工作进程中执行也不等于具有并行感知能力。\u003c/p\u003e\u003ch3\u003e同版本中文手册节选\u003c/h3\u003e\u003cp\u003e\n\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e 通过分两个阶段进行聚合来支持并行聚合。首先，每个参与查询并行部分的进程执行一个聚合步骤，为该进程所见到的每个分组产生一个部分结果。这在计划中体现为一个 \u003ccode class=\"literal\"\u003ePartial Aggregate\u003c/code\u003e 节点。然后，部分结果通过 \u003ccode class=\"literal\"\u003eGather\u003c/code\u003e 或 \u003ccode class=\"literal\"\u003eGather Merge\u003c/code\u003e 传送给领导者。最后，领导者会把来自所有工作进程的结果再次聚合，以产生最终结果。这在计划中体现为一个 \u003ccode class=\"literal\"\u003eFinalize Aggregate\u003c/code\u003e 节点。\n  \u003c/p\u003e\u003cp\u003e\n    由于 \u003ccode class=\"literal\"\u003eFinalize Aggregate\u003c/code\u003e 节点运行在领导者进程上，因此对于那些相对于输入行数会产生较多分组的查询，查询规划器会认为它不太有利。例如，在最坏情况下，\u003ccode class=\"literal\"\u003eFinalize Aggregate\u003c/code\u003e 节点看到的分组数可能与所有工作进程在 \u003ccode class=\"literal\"\u003ePartial Aggregate\u003c/code\u003e 阶段看到的输入行数一样多。对于这种情况，使用并行聚合显然不会带来性能收益。查询规划器会在规划过程中考虑这一点，因此在这种场景下不太可能选择并行聚合。\n  \u003c/p\u003e\u003cp\u003e\n    并行聚合并非在所有情况下都受支持。每个聚合都必须是\u003ca class=\"link\" href=\"/zh/docs/18/parallel-safety.html\"\u003e并行安全\u003c/a\u003e的，并且必须具有合并函数。如果该聚合具有类型为 \u003ccode class=\"literal\"\u003einternal\u003c/code\u003e 的转移状态，那么它还必须具有序列化和反序列化函数。更多细节请参见 \u003ca class=\"xref\" href=\"/zh/docs/18/sql-createaggregate.html\"\u003e\u003cspan class=\"refentrytitle\"\u003eCREATE AGGREGATE\u003c/span\u003e\u003c/a\u003e。如果任何聚合函数调用包含 \u003ccode class=\"literal\"\u003eDISTINCT\u003c/code\u003e 或 \u003ccode class=\"literal\"\u003eORDER BY\u003c/code\u003e 子句，则不支持并行聚合。对于有序集聚合，或者当查询涉及 \u003ccode class=\"literal\"\u003eGROUPING SETS\u003c/code\u003e 时，也不支持并行聚合。只有当查询涉及的所有连接也都属于计划并行部分时，才能使用并行聚合。\n  \u003c/p\u003e\u003cp\u003e\u003ca href=\"/zh/docs/18/parallel-plans.html#PARALLEL-AGGREGATION\"\u003e查看完整中文手册与上下文\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e本页开头的中文说明为 PG.CENTER 对编辑说明的翻译；手册节选保留对应版本中文文档原文。源码信息及手册示例不代表重新进行过运行测试。\u003c/p\u003e","evidence_kind":"source and documentation","explain_names":["Group"],"explain_prefixes":["Parallel","Async"],"facts":[{"label":"Core node tag","value":"T_Group"},{"label":"Structured EXPLAIN Node Type","value":"Group"},{"label":"Inputs","value":"One ordered child plan"},{"label":"Output","value":"One tuple per group"},{"label":"Executor initializer","value":"ExecInitGroup"},{"label":"Memory mechanism","value":"unclassified"}],"facts_zh":[{"label":"核心节点标签","value":"T_Group"},{"label":"结构化 EXPLAIN 节点类型","value":"Group"},{"label":"输入","value":"一个有序子计划"},{"label":"输出","value":"每组一个元组"},{"label":"执行器初始化函数","value":"ExecInitGroup"},{"label":"内存机制","value":"unclassified"}],"memory":{"description":"This extraction does not assign a universal memory limit or spill policy to this node. Inspect the same-build implementation and its expressions or provider.","evidence":[{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/nodeGroup.c","path":"src/backend/executor/nodeGroup.c","sha256":"c253c59d9928373ed62124342d5c314a4c52968a2fcc9399c39a3e1bab4fdbbf","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"}],"mechanism":"unclassified","source_notes":[]},"node_tag":"T_Group","parallel_callbacks":[],"partial_modes":[],"related":[{"label":"EXPLAIN","url":"/wiki/sql/explain/?v=18"},{"label":"Using EXPLAIN","url":"/docs/18/using-explain.html"},{"label":"Parallel plans","url":"/docs/18/parallel-plans.html"}],"release":{"channel":"stable","label":"18.6","major":"18","ref":"PostgreSQL 18.6 source archive","revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","source_snapshot_utc":"","source_url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},"runtime_verified":false,"sections":[{"paragraphs":["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.","Text names recorded by this source: Group.","Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."],"title":"EXPLAIN names and attributes"},{"paragraphs":["This extraction does not assign a universal memory limit or spill policy to this node. Inspect the same-build implementation and its expressions or provider."],"title":"Memory and temporary storage"},{"paragraphs":["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.","Callbacks in this build: none extracted from this node implementation."],"title":"Parallel execution and instrumentation"},{"paragraphs":["PostgreSQL supports parallel aggregation by aggregating in two stages. First, each process participating in the parallel portion of the query performs an aggregation step, producing a partial result for each group of which that process is aware. This is reflected in the plan as a Partial Aggregate node. Second, the partial results are transferred to the leader via Gather or Gather Merge . Finally, the leader re-aggregates the results across all workers in order to produce the final result. This is reflected in the plan as a Finalize Aggregate node."],"title":"Same-version manual discussion"},{"paragraphs":["nodeGroup.c Routines to handle group nodes (used for queries with GROUP BY clause).","DESCRIPTION The Group node is designed for handling queries with a GROUP BY clause. Its outer plan must deliver tuples that are sorted in the order specified by the grouping columns (ie. tuples from the same group are consecutive). That way, we just have to compare adjacent tuples to locate group boundaries.","The ScanTupleSlot holds the (copied) first tuple of each group.","We need not call ResetExprContext here because ExecQualAndReset() will reset the per-tuple memory context once per input tuple.","If first time through, acquire first input tuple and determine whether to return it or not."],"title":"Executor implementation notes"},{"code":"case T_Group:\n\t\t\tpname = sname = \"Group\";\n\t\t\tbreak;","title":"EXPLAIN identity in core source"}],"sections_zh":[{"paragraphs":["结构化格式使用上述 Node Type。文本格式名称还可能包含操作、策略、连接类型、扫描方向或聚合阶段属性。","此源码记录的文本名称：Group.","并行感知与并行安全是不同的计划属性。在并行工作进程内运行的节点不一定是并行感知节点。"],"title":"EXPLAIN 名称与属性"},{"paragraphs":["本次抽取不为此节点设定统一的内存上限或落盘策略。请查看同一构建的实现、相关表达式或提供方。"],"title":"内存与临时存储"},{"paragraphs":["以下源码回调可以协调执行或收集工作进程的测量数据。回调存在不代表该节点普遍支持共享并行扫描或共享状态。","此构建的回调：none extracted from this node implementation."],"title":"并行执行与运行信息采集"},{"paragraphs":["PostgreSQL 通过分两个阶段进行聚合来支持并行聚合。首先，每个参与查询并行部分的进程执行一个聚合步骤，为该进程所见到的每个分组产生一个部分结果。这在计划中体现为一个 Partial Aggregate 节点。然后，部分结果通过 Gather 或 Gather Merge 传送给领导者。最后，领导者会把来自所有工作进程的结果再次聚合，以产生最终结果。这在计划中体现为一个 Finalize Aggregate 节点。"],"title":"同版本手册说明"},{"paragraphs":["nodeGroup.c：处理 Group 节点（用于带 GROUP BY 子句的查询）的例程。","说明：Group 节点用于处理包含 GROUP BY 子句的查询。它的外侧计划必须按分组列指定的顺序输出元组，即同组元组必须连续。这样，只需比较相邻元组即可确定分组边界。","ScanTupleSlot 保存每个组的第一个元组的副本。","此处无需调用 ResetExprContext，因为 ExecQualAndReset() 会为每个输入元组重置一次逐元组内存上下文。","首次执行时，获取第一个输入元组，并判断是否应返回它。"],"title":"执行器实现说明"},{"code":"case T_Group:\n\t\t\tpname = sname = \"Group\";\n\t\t\tbreak;","title":"核心源码中的 EXPLAIN 标识"}],"source_inventory":{"executor":"src/backend/executor/execProcnode.c","explain":"src/backend/commands/explain.c","implementation":"src/backend/executor/nodeGroup.c"},"sources":[{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/commands/explain.c:1528","line":1528,"path":"src/backend/commands/explain.c","sha256":"34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/execProcnode.c:335","line":335,"path":"src/backend/executor/execProcnode.c","sha256":"f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/nodeGroup.c","path":"src/backend/executor/nodeGroup.c","sha256":"c253c59d9928373ed62124342d5c314a4c52968a2fcc9399c39a3e1bab4fdbbf","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/include/nodes/plannodes.h","path":"src/include/nodes/plannodes.h","sha256":"52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"label":"PostgreSQL 18.6 · parallel-plans","path":"parallel-plans.html","sha256":"62207d207bead82b01b59dc119c4f95856f08655cc11d4699a05a40867ed2070","url":"/docs/18/parallel-plans.html#PARALLEL-AGGREGATION"}],"strategies":[],"tables":[{"columns":[{"key":"label","label":"Text-format label"},{"key":"identity","label":"Structured node identity"}],"key":"explain-labels","rows":[{"identity":"Group","label":"Group"}],"title":"EXPLAIN labels in this source build"}],"tables_zh":[{"columns":[{"key":"label","label":"文本格式标签"},{"key":"identity","label":"结构化节点标识"}],"key":"explain-labels","rows":[{"identity":"Group","label":"Group"}],"title":"本构建中的 EXPLAIN 标签"}],"zh_from":{"authored_translation":"authored-translation-of-reviewed-guidance","body_sha256":"a94539ce6d36f921fe710cfca4476dc2c3835d18f37706eed31232b5f33be3d2","kind":"same-version-chinese-manual-with-authored-translation-of-reviewed-guidance","manual":{"anchor":"PARALLEL-AGGREGATION","build_id":107,"extraction":"concept-introduction","fragment_sha256":"f882e19de96b3173fd88cb5de956b736c655192b92b7cdbf544225b9bedc6662","locale":"zh-Hans","page_key":"parallel-plans.html","source_hash":"1ef9f9a3740440f8dcdf04c2a2dfe2f7d48c66f2e0b102d15df580bff22a6857","source_revision":"unknown:rendered-translation-baseline","translated_from_revision":null,"translation_revision":"git:b1b500221dbe5437cfca004d6b04d3f6e422765d;html-sha256:08e987a66af27b98444a8057c256314eafa13611a3fb9e888214fc436824244b","url":"/zh/docs/18/parallel-plans.html#PARALLEL-AGGREGATION","version":"18"},"runtime_rerun":false,"source_facts_revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}},"ManualEvidence":{"release":{"channel":"stable","label":"18.6","major":"18","ref":"PostgreSQL 18.6 source archive","revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","source_snapshot_utc":"","source_url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},"sources":[{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/commands/explain.c:1528","line":1528,"path":"src/backend/commands/explain.c","sha256":"34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/execProcnode.c:335","line":335,"path":"src/backend/executor/execProcnode.c","sha256":"f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/nodeGroup.c","path":"src/backend/executor/nodeGroup.c","sha256":"c253c59d9928373ed62124342d5c314a4c52968a2fcc9399c39a3e1bab4fdbbf","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/include/nodes/plannodes.h","path":"src/include/nodes/plannodes.h","sha256":"52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"label":"PostgreSQL 18.6 · parallel-plans","path":"parallel-plans.html","sha256":"62207d207bead82b01b59dc119c4f95856f08655cc11d4699a05a40867ed2070","url":"/docs/18/parallel-plans.html#PARALLEL-AGGREGATION"}]},"MeasuredEvidence":{"runtime_verified":false}},"Text":{"Collection":"plan","Key":"group","SourceDatabase":"center","Version":"18","Locale":"en","Title":"Group","Summary":"Groups an ordered input stream by its grouping columns.","BodyHTML":"\u003cp\u003eGroups an ordered input stream by its grouping columns.\u003c/p\u003e","SourceRevision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","ContentHash":"295778e2d012601883e165b76ab1666ea91cb33613eea30ef1008026929db0e8","Payload":{"description":["Groups an ordered input stream by its grouping columns."],"related":[{"label":"EXPLAIN","url":"/wiki/sql/explain/?v=18"},{"label":"Using EXPLAIN","url":"/docs/18/using-explain.html"},{"label":"Parallel plans","url":"/docs/18/parallel-plans.html"}],"sections":[{"paragraphs":["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.","Text names recorded by this source: Group.","Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."],"title":"EXPLAIN names and attributes"},{"paragraphs":["This extraction does not assign a universal memory limit or spill policy to this node. Inspect the same-build implementation and its expressions or provider."],"title":"Memory and temporary storage"},{"paragraphs":["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.","Callbacks in this build: none extracted from this node implementation."],"title":"Parallel execution and instrumentation"},{"paragraphs":["PostgreSQL supports parallel aggregation by aggregating in two stages. First, each process participating in the parallel portion of the query performs an aggregation step, producing a partial result for each group of which that process is aware. This is reflected in the plan as a Partial Aggregate node. Second, the partial results are transferred to the leader via Gather or Gather Merge . Finally, the leader re-aggregates the results across all workers in order to produce the final result. This is reflected in the plan as a Finalize Aggregate node."],"title":"Same-version manual discussion"},{"paragraphs":["nodeGroup.c Routines to handle group nodes (used for queries with GROUP BY clause).","DESCRIPTION The Group node is designed for handling queries with a GROUP BY clause. Its outer plan must deliver tuples that are sorted in the order specified by the grouping columns (ie. tuples from the same group are consecutive). That way, we just have to compare adjacent tuples to locate group boundaries.","The ScanTupleSlot holds the (copied) first tuple of each group.","We need not call ResetExprContext here because ExecQualAndReset() will reset the per-tuple memory context once per input tuple.","If first time through, acquire first input tuple and determine whether to return it or not."],"title":"Executor implementation notes"},{"code":"case T_Group:\n\t\t\tpname = sname = \"Group\";\n\t\t\tbreak;","title":"EXPLAIN identity in core source"}],"tables":[{"columns":[{"key":"label","label":"Text-format label"},{"key":"identity","label":"Structured node identity"}],"key":"explain-labels","rows":[{"identity":"Group","label":"Group"}],"title":"EXPLAIN labels in this source build"}]}},"RequestedLocale":"en","Fallback":false,"Versions":["10","11","12","13","14","15","16","17","18","19","20"],"Locales":["en","zh-Hans"],"Signatures":null,"Spellings":null,"SQLState":null,"Evidence":null}
