{"kind": "plan", "major": "18", "item": {"slug": "recursive-union", "name": "Recursive Union", "name_zh": "RecursiveUnion", "category": "\u7ec4\u5408", "summary": "\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002", "aliases": ["Recursive Union", "RecursiveUnion", "T_RecursiveUnion"], "content_hash": "e93e1befd57f81fe94252188eab2986940415c40efa81ed0fc2e7a3efe305131", "versions": {"10": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "01b05e8d64377338e2db2885568ccf521facba826fbb2a841d5536a7f6a49e3e", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "dcf45a15db0b6fce8d77783138557f9fcb956b5c45dceac9ec734c2990f8cb97", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=10", "label": "EXPLAIN"}, {"url": "/docs/10/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/10/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=10", "label": "work_mem"}], "release": {"ref": "PostgreSQL 10.23 source archive", "label": "10.23", "major": "10", "channel": "historical", "revision": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9", "source_url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "line": 912, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:912", "sha256": "a785298532047cfeda969e78c3597a343dc1c56d61ba85830b0f16a02a14b5a1", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "line": 189, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:189", "sha256": "cea76648bb38ae55f18f989768bee1a4ee025691ceea0f86bccb29dcdc166acc", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "01b05e8d64377338e2db2885568ccf521facba826fbb2a841d5536a7f6a49e3e", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "d562c321108844798cd234303fffb618f13d4ee3f3a5ac79bfd963b077e47c22", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "dcf45a15db0b6fce8d77783138557f9fcb956b5c45dceac9ec734c2990f8cb97", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002", "\u4f7f\u7528\u54c8\u5e0c\u65f6\uff0c\u9700\u8981\u4e00\u4e2a\u7528\u4e8e\u6bd4\u8f83\u7684\u5143\u7ec4\u7ea7\u5185\u5b58\u4e0a\u4e0b\u6587\uff0c\u4ee5\u53ca\u4e00\u4e2a\u751f\u547d\u5468\u671f\u66f4\u957f\u3001\u7528\u4e8e\u5b58\u50a8\u54c8\u5e0c\u8868\u7684\u4e0a\u4e0b\u6587\u3002\u4e0d\u80fd\u76f4\u63a5\u5c06\u54c8\u5e0c\u8868\u4fdd\u5b58\u5728\u67e5\u8be2\u7ea7\u4e0a\u4e0b\u6587\u4e2d\uff0c\u56e0\u4e3a\u91cd\u626b\u65f6\u9700\u8981\u80fd\u4e22\u5f03\u5b83\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/10/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/10/facts/0/label": "Core node tag", "/versions/10/facts/1/label": "Structured EXPLAIN Node Type", "/versions/10/facts/2/label": "Inputs", "/versions/10/facts/2/value": "Non-recursive and recursive child plans", "/versions/10/facts/3/label": "Output", "/versions/10/facts/3/value": "Recursive query tuples", "/versions/10/facts/4/label": "Executor initializer", "/versions/10/facts/5/label": "Memory mechanism", "/versions/10/tables/0/title": "EXPLAIN labels in this source build", "/versions/10/related/1/label": "Using EXPLAIN", "/versions/10/related/2/label": "Parallel plans", "/versions/10/sections/0/title": "EXPLAIN names and attributes", "/versions/10/sections/1/title": "Memory and temporary storage", "/versions/10/sections/2/title": "Parallel execution and instrumentation", "/versions/10/sections/3/title": "Executor implementation notes", "/versions/10/sections/4/title": "EXPLAIN identity in core source", "/versions/10/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/10/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/10/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/10/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/10/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/10/sections/2/paragraphs/0": "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.", "/versions/10/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/10/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/10/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/10/sections/3/paragraphs/2": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/10/sections/3/paragraphs/3": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/10/sections/3/paragraphs/4": "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning.", "/versions/10/tables/0/columns/0/label": "Text-format label", "/versions/10/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "cd8f9ebc573f4de44cf96fbdfb02796ec88ed12be06c5e686bfe9604453fc095"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "11": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "629f26d49096e84125f6bd83ddaa189cd0945229ab7357c744d2dc9051a0b7c5", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "2891704a2b38e4f4c52cce4604f1cad8b83781217697c4cddd6d3d99ddc14fce", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=11", "label": "EXPLAIN"}, {"url": "/docs/11/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/11/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=11", "label": "work_mem"}], "release": {"ref": "PostgreSQL 11.22 source archive", "label": "11.22", "major": "11", "channel": "historical", "revision": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0", "source_url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "line": 1037, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1037", "sha256": "9df8400c1a4377179572ceb916d6020fca4e2760f74bf416d77ed97476523bbd", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "line": 189, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:189", "sha256": "95ef4d4a5df4c29f14af9763fae2c530449bdacdf3853d9ff297adf1fed6153b", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "629f26d49096e84125f6bd83ddaa189cd0945229ab7357c744d2dc9051a0b7c5", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "5e0511194183800e8d6eb293fd4b40639c7d3118e2d199c8e7865ba4fa4cf67f", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "2891704a2b38e4f4c52cce4604f1cad8b83781217697c4cddd6d3d99ddc14fce", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002", "\u4f7f\u7528\u54c8\u5e0c\u65f6\uff0c\u9700\u8981\u4e00\u4e2a\u7528\u4e8e\u6bd4\u8f83\u7684\u5143\u7ec4\u7ea7\u5185\u5b58\u4e0a\u4e0b\u6587\uff0c\u4ee5\u53ca\u4e00\u4e2a\u751f\u547d\u5468\u671f\u66f4\u957f\u3001\u7528\u4e8e\u5b58\u50a8\u54c8\u5e0c\u8868\u7684\u4e0a\u4e0b\u6587\u3002\u4e0d\u80fd\u76f4\u63a5\u5c06\u54c8\u5e0c\u8868\u4fdd\u5b58\u5728\u67e5\u8be2\u7ea7\u4e0a\u4e0b\u6587\u4e2d\uff0c\u56e0\u4e3a\u91cd\u626b\u65f6\u9700\u8981\u80fd\u4e22\u5f03\u5b83\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/11/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/11/facts/0/label": "Core node tag", "/versions/11/facts/1/label": "Structured EXPLAIN Node Type", "/versions/11/facts/2/label": "Inputs", "/versions/11/facts/2/value": "Non-recursive and recursive child plans", "/versions/11/facts/3/label": "Output", "/versions/11/facts/3/value": "Recursive query tuples", "/versions/11/facts/4/label": "Executor initializer", "/versions/11/facts/5/label": "Memory mechanism", "/versions/11/tables/0/title": "EXPLAIN labels in this source build", "/versions/11/related/1/label": "Using EXPLAIN", "/versions/11/related/2/label": "Parallel plans", "/versions/11/sections/0/title": "EXPLAIN names and attributes", "/versions/11/sections/1/title": "Memory and temporary storage", "/versions/11/sections/2/title": "Parallel execution and instrumentation", "/versions/11/sections/3/title": "Executor implementation notes", "/versions/11/sections/4/title": "EXPLAIN identity in core source", "/versions/11/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/11/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/11/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/11/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/11/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/11/sections/2/paragraphs/0": "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.", "/versions/11/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/11/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/11/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/11/sections/3/paragraphs/2": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/11/sections/3/paragraphs/3": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/11/sections/3/paragraphs/4": "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning.", "/versions/11/tables/0/columns/0/label": "Text-format label", "/versions/11/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "cb9c1988ae2157b566aacf36bd4eb70b0c265b75099d623e42802978d8fb59e5"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "12": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "43e465f94085eb2f6df02e38f5e3347909a878cb22ce21f730a1d0c60f4357f4", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "44cccd98d659272f5c8f3ff6adffb1f6cc911acd13a3cfafc74cc7841318f929", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=12", "label": "EXPLAIN"}, {"url": "/docs/12/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/12/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=12", "label": "work_mem"}], "release": {"ref": "PostgreSQL 12.22 source archive", "label": "12.22", "major": "12", "channel": "historical", "revision": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b", "source_url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "line": 1108, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1108", "sha256": "d02ea84fdaa201de5d9360645a9f24bfbd2c31f7d45a639e09560ac0e6b6471d", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "line": 189, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:189", "sha256": "311b17379fe54e3f342fe5ad41c43afbdfa1b844978db2bb2eb22b82520d3256", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "43e465f94085eb2f6df02e38f5e3347909a878cb22ce21f730a1d0c60f4357f4", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "b0c4a0aeb48660ce06e5e700d5529ca9066fd16682bd15783d6e71b5420b07b0", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "44cccd98d659272f5c8f3ff6adffb1f6cc911acd13a3cfafc74cc7841318f929", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002", "\u4f7f\u7528\u54c8\u5e0c\u65f6\uff0c\u9700\u8981\u4e00\u4e2a\u7528\u4e8e\u6bd4\u8f83\u7684\u5143\u7ec4\u7ea7\u5185\u5b58\u4e0a\u4e0b\u6587\uff0c\u4ee5\u53ca\u4e00\u4e2a\u751f\u547d\u5468\u671f\u66f4\u957f\u3001\u7528\u4e8e\u5b58\u50a8\u54c8\u5e0c\u8868\u7684\u4e0a\u4e0b\u6587\u3002\u4e0d\u80fd\u76f4\u63a5\u5c06\u54c8\u5e0c\u8868\u4fdd\u5b58\u5728\u67e5\u8be2\u7ea7\u4e0a\u4e0b\u6587\u4e2d\uff0c\u56e0\u4e3a\u91cd\u626b\u65f6\u9700\u8981\u80fd\u4e22\u5f03\u5b83\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/12/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/12/facts/0/label": "Core node tag", "/versions/12/facts/1/label": "Structured EXPLAIN Node Type", "/versions/12/facts/2/label": "Inputs", "/versions/12/facts/2/value": "Non-recursive and recursive child plans", "/versions/12/facts/3/label": "Output", "/versions/12/facts/3/value": "Recursive query tuples", "/versions/12/facts/4/label": "Executor initializer", "/versions/12/facts/5/label": "Memory mechanism", "/versions/12/tables/0/title": "EXPLAIN labels in this source build", "/versions/12/related/1/label": "Using EXPLAIN", "/versions/12/related/2/label": "Parallel plans", "/versions/12/sections/0/title": "EXPLAIN names and attributes", "/versions/12/sections/1/title": "Memory and temporary storage", "/versions/12/sections/2/title": "Parallel execution and instrumentation", "/versions/12/sections/3/title": "Executor implementation notes", "/versions/12/sections/4/title": "EXPLAIN identity in core source", "/versions/12/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/12/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/12/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/12/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/12/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/12/sections/2/paragraphs/0": "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.", "/versions/12/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/12/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/12/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/12/sections/3/paragraphs/2": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/12/sections/3/paragraphs/3": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/12/sections/3/paragraphs/4": "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning.", "/versions/12/tables/0/columns/0/label": "Text-format label", "/versions/12/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "84cb9671622c58378cbe115c3923c7cf7ad820bbbf937623b0926777b2cb426c"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "13": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "4c890bc0389b519e50d3452ce9e15bf0d028b9eb32f5dfe0d6ffdc3a58009fb0", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "4cba6490949d7dd9338b8499fcbb489e84cfd6cda9b98599512eb40bfbde6f9d", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=13", "label": "EXPLAIN"}, {"url": "/docs/13/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/13/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=13", "label": "work_mem"}], "release": {"ref": "PostgreSQL 13.23 source archive", "label": "13.23", "major": "13", "channel": "historical", "revision": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6", "source_url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "line": 1166, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1166", "sha256": "541713e0e7f1c9cc352c2b6028964d440c19d2678a4463000094c24a88c1e730", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "line": 189, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:189", "sha256": "d085ee99acfa00587e6ade3a1d9f8108a0566beedbbee3f54a50c9fc0cc2e875", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "4c890bc0389b519e50d3452ce9e15bf0d028b9eb32f5dfe0d6ffdc3a58009fb0", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "dcb296833777b02008c4b6bae8e8f7c6423b7ffba21f36702597c9d596d039ab", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "4cba6490949d7dd9338b8499fcbb489e84cfd6cda9b98599512eb40bfbde6f9d", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002", "\u4f7f\u7528\u54c8\u5e0c\u65f6\uff0c\u9700\u8981\u4e00\u4e2a\u7528\u4e8e\u6bd4\u8f83\u7684\u5143\u7ec4\u7ea7\u5185\u5b58\u4e0a\u4e0b\u6587\uff0c\u4ee5\u53ca\u4e00\u4e2a\u751f\u547d\u5468\u671f\u66f4\u957f\u3001\u7528\u4e8e\u5b58\u50a8\u54c8\u5e0c\u8868\u7684\u4e0a\u4e0b\u6587\u3002\u4e0d\u80fd\u76f4\u63a5\u5c06\u54c8\u5e0c\u8868\u4fdd\u5b58\u5728\u67e5\u8be2\u7ea7\u4e0a\u4e0b\u6587\u4e2d\uff0c\u56e0\u4e3a\u91cd\u626b\u65f6\u9700\u8981\u80fd\u4e22\u5f03\u5b83\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/13/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/13/facts/0/label": "Core node tag", "/versions/13/facts/1/label": "Structured EXPLAIN Node Type", "/versions/13/facts/2/label": "Inputs", "/versions/13/facts/2/value": "Non-recursive and recursive child plans", "/versions/13/facts/3/label": "Output", "/versions/13/facts/3/value": "Recursive query tuples", "/versions/13/facts/4/label": "Executor initializer", "/versions/13/facts/5/label": "Memory mechanism", "/versions/13/tables/0/title": "EXPLAIN labels in this source build", "/versions/13/related/1/label": "Using EXPLAIN", "/versions/13/related/2/label": "Parallel plans", "/versions/13/sections/0/title": "EXPLAIN names and attributes", "/versions/13/sections/1/title": "Memory and temporary storage", "/versions/13/sections/2/title": "Parallel execution and instrumentation", "/versions/13/sections/3/title": "Executor implementation notes", "/versions/13/sections/4/title": "EXPLAIN identity in core source", "/versions/13/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/13/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/13/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/13/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/13/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/13/sections/2/paragraphs/0": "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.", "/versions/13/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/13/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/13/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/13/sections/3/paragraphs/2": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/13/sections/3/paragraphs/3": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/13/sections/3/paragraphs/4": "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning.", "/versions/13/tables/0/columns/0/label": "Text-format label", "/versions/13/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "1e1992032f9fb92ae3f145d54601e23c41f16bdeea7ff6de219b648542e1f2d4"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "14": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "1fa4a12d45ae59b313d2c449ea1e7564f3c986c5f4b2b391e9b0b01e6038c716", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "833cff27e0a2c863b9e897cd3bf4127df1b3e3a9b976694f3323a1c1a466d9b2", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=14", "label": "EXPLAIN"}, {"url": "/docs/14/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/14/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=14", "label": "work_mem"}], "release": {"ref": "PostgreSQL 14.24 source archive", "label": "14.24", "major": "14", "channel": "stable", "revision": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897", "source_url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "line": 1202, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1202", "sha256": "e091be4e2a083b8dea39ccd09beedede22c1716ef974da66c214a44f48be8c41", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "72da1c5ad457f1d92a39ab73531701794df858419e3b89d6e6cb7079634e68fa", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "1fa4a12d45ae59b313d2c449ea1e7564f3c986c5f4b2b391e9b0b01e6038c716", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "302f51a16b570dba7ec4e7bc045f7df5800d21630280354d1a24025f3baec75d", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "833cff27e0a2c863b9e897cd3bf4127df1b3e3a9b976694f3323a1c1a466d9b2", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002", "\u4f7f\u7528\u54c8\u5e0c\u65f6\uff0c\u9700\u8981\u4e00\u4e2a\u7528\u4e8e\u6bd4\u8f83\u7684\u5143\u7ec4\u7ea7\u5185\u5b58\u4e0a\u4e0b\u6587\uff0c\u4ee5\u53ca\u4e00\u4e2a\u751f\u547d\u5468\u671f\u66f4\u957f\u3001\u7528\u4e8e\u5b58\u50a8\u54c8\u5e0c\u8868\u7684\u4e0a\u4e0b\u6587\u3002\u4e0d\u80fd\u76f4\u63a5\u5c06\u54c8\u5e0c\u8868\u4fdd\u5b58\u5728\u67e5\u8be2\u7ea7\u4e0a\u4e0b\u6587\u4e2d\uff0c\u56e0\u4e3a\u91cd\u626b\u65f6\u9700\u8981\u80fd\u4e22\u5f03\u5b83\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/14/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/14/facts/0/label": "Core node tag", "/versions/14/facts/1/label": "Structured EXPLAIN Node Type", "/versions/14/facts/2/label": "Inputs", "/versions/14/facts/2/value": "Non-recursive and recursive child plans", "/versions/14/facts/3/label": "Output", "/versions/14/facts/3/value": "Recursive query tuples", "/versions/14/facts/4/label": "Executor initializer", "/versions/14/facts/5/label": "Memory mechanism", "/versions/14/tables/0/title": "EXPLAIN labels in this source build", "/versions/14/related/1/label": "Using EXPLAIN", "/versions/14/related/2/label": "Parallel plans", "/versions/14/sections/0/title": "EXPLAIN names and attributes", "/versions/14/sections/1/title": "Memory and temporary storage", "/versions/14/sections/2/title": "Parallel execution and instrumentation", "/versions/14/sections/3/title": "Executor implementation notes", "/versions/14/sections/4/title": "EXPLAIN identity in core source", "/versions/14/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/14/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/14/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/14/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/14/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/14/sections/2/paragraphs/0": "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.", "/versions/14/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/14/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/14/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/14/sections/3/paragraphs/2": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/14/sections/3/paragraphs/3": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/14/sections/3/paragraphs/4": "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning.", "/versions/14/tables/0/columns/0/label": "Text-format label", "/versions/14/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "99201bbc9631133b4946b24458b5f58ce3b636cc09c5e5a346507753b5a40412"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "15": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "1021c1580f1046f9f297f35520c208f6707e14f05ab8596ba23d7ecf7e814846", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "37be0ffb18c97558ea6fe6e1e0072564026b231edb9edf0a29faf27f13827aab", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=15", "label": "EXPLAIN"}, {"url": "/docs/15/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/15/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=15", "label": "work_mem"}], "release": {"ref": "PostgreSQL 15.19 source archive", "label": "15.19", "major": "15", "channel": "stable", "revision": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89", "source_url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "line": 1205, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1205", "sha256": "bb3b442d0f1b098aa8707335250102f027a596cd94117308bd16d1d36b258f5c", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "19836c50a272741a4eac653541e655437c2e00710a541e5348d6a277d0669d7c", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "1021c1580f1046f9f297f35520c208f6707e14f05ab8596ba23d7ecf7e814846", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "fb4a4c8165495299131173680bc02a950d88e1ff610231fd97997bc0c9afc1d7", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "37be0ffb18c97558ea6fe6e1e0072564026b231edb9edf0a29faf27f13827aab", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002", "\u4f7f\u7528\u54c8\u5e0c\u65f6\uff0c\u9700\u8981\u4e00\u4e2a\u7528\u4e8e\u6bd4\u8f83\u7684\u5143\u7ec4\u7ea7\u5185\u5b58\u4e0a\u4e0b\u6587\uff0c\u4ee5\u53ca\u4e00\u4e2a\u751f\u547d\u5468\u671f\u66f4\u957f\u3001\u7528\u4e8e\u5b58\u50a8\u54c8\u5e0c\u8868\u7684\u4e0a\u4e0b\u6587\u3002\u4e0d\u80fd\u76f4\u63a5\u5c06\u54c8\u5e0c\u8868\u4fdd\u5b58\u5728\u67e5\u8be2\u7ea7\u4e0a\u4e0b\u6587\u4e2d\uff0c\u56e0\u4e3a\u91cd\u626b\u65f6\u9700\u8981\u80fd\u4e22\u5f03\u5b83\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/15/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/15/facts/0/label": "Core node tag", "/versions/15/facts/1/label": "Structured EXPLAIN Node Type", "/versions/15/facts/2/label": "Inputs", "/versions/15/facts/2/value": "Non-recursive and recursive child plans", "/versions/15/facts/3/label": "Output", "/versions/15/facts/3/value": "Recursive query tuples", "/versions/15/facts/4/label": "Executor initializer", "/versions/15/facts/5/label": "Memory mechanism", "/versions/15/tables/0/title": "EXPLAIN labels in this source build", "/versions/15/related/1/label": "Using EXPLAIN", "/versions/15/related/2/label": "Parallel plans", "/versions/15/sections/0/title": "EXPLAIN names and attributes", "/versions/15/sections/1/title": "Memory and temporary storage", "/versions/15/sections/2/title": "Parallel execution and instrumentation", "/versions/15/sections/3/title": "Executor implementation notes", "/versions/15/sections/4/title": "EXPLAIN identity in core source", "/versions/15/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/15/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/15/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/15/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/15/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/15/sections/2/paragraphs/0": "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.", "/versions/15/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/15/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/15/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/15/sections/3/paragraphs/2": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/15/sections/3/paragraphs/3": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/15/sections/3/paragraphs/4": "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning.", "/versions/15/tables/0/columns/0/label": "Text-format label", "/versions/15/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "8a582cc7d933cdb36bc2ef490d17dc2ed5021d81ead117fac73d8583b3b09193"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "16": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "8528ec1bbb53dfcd43f842e34dcd9307dbae5d299b6cd55aaefc39ef57e9ace8", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "a990669858f1847ac83b5e1e65cf5515fe05ea0ad45ff64dd9347ba4f2110e62", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=16", "label": "EXPLAIN"}, {"url": "/docs/16/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/16/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=16", "label": "work_mem"}], "release": {"ref": "PostgreSQL 16.15 source archive", "label": "16.15", "major": "16", "channel": "stable", "revision": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed", "source_url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "line": 1238, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1238", "sha256": "8e017f0116dbea471339b40c37a667cc9f95039e7e0329c783e5e8ce194de7e1", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "e48c08e555f8cb4e4bb43df516c4b8906ce9bc374b2a745d98a1fc8c22cc5099", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "8528ec1bbb53dfcd43f842e34dcd9307dbae5d299b6cd55aaefc39ef57e9ace8", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "97db47353db76326b874589a5ad0a04501cc74cd72e237e7bd956e7472c41f1f", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "a990669858f1847ac83b5e1e65cf5515fe05ea0ad45ff64dd9347ba4f2110e62", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002", "\u4f7f\u7528\u54c8\u5e0c\u65f6\uff0c\u9700\u8981\u4e00\u4e2a\u7528\u4e8e\u6bd4\u8f83\u7684\u5143\u7ec4\u7ea7\u5185\u5b58\u4e0a\u4e0b\u6587\uff0c\u4ee5\u53ca\u4e00\u4e2a\u751f\u547d\u5468\u671f\u66f4\u957f\u3001\u7528\u4e8e\u5b58\u50a8\u54c8\u5e0c\u8868\u7684\u4e0a\u4e0b\u6587\u3002\u4e0d\u80fd\u76f4\u63a5\u5c06\u54c8\u5e0c\u8868\u4fdd\u5b58\u5728\u67e5\u8be2\u7ea7\u4e0a\u4e0b\u6587\u4e2d\uff0c\u56e0\u4e3a\u91cd\u626b\u65f6\u9700\u8981\u80fd\u4e22\u5f03\u5b83\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/16/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/16/facts/0/label": "Core node tag", "/versions/16/facts/1/label": "Structured EXPLAIN Node Type", "/versions/16/facts/2/label": "Inputs", "/versions/16/facts/2/value": "Non-recursive and recursive child plans", "/versions/16/facts/3/label": "Output", "/versions/16/facts/3/value": "Recursive query tuples", "/versions/16/facts/4/label": "Executor initializer", "/versions/16/facts/5/label": "Memory mechanism", "/versions/16/tables/0/title": "EXPLAIN labels in this source build", "/versions/16/related/1/label": "Using EXPLAIN", "/versions/16/related/2/label": "Parallel plans", "/versions/16/sections/0/title": "EXPLAIN names and attributes", "/versions/16/sections/1/title": "Memory and temporary storage", "/versions/16/sections/2/title": "Parallel execution and instrumentation", "/versions/16/sections/3/title": "Executor implementation notes", "/versions/16/sections/4/title": "EXPLAIN identity in core source", "/versions/16/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/16/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/16/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/16/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/16/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/16/sections/2/paragraphs/0": "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.", "/versions/16/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/16/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/16/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/16/sections/3/paragraphs/2": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/16/sections/3/paragraphs/3": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/16/sections/3/paragraphs/4": "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning.", "/versions/16/tables/0/columns/0/label": "Text-format label", "/versions/16/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "4618fd65fb257b4b6b01c0247f9ffedc9604b966f6699c2a1470342fcbda6f21"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "17": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "f03122d0aba6181ea442d719d6ba99f851c5eefe4b9c255ecf1b1e3636e0efe1", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "0d4316ed2d09288c2e3be15be1ce01b88622354bcd571ac7ebc45aa9319b90e7", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=17", "label": "EXPLAIN"}, {"url": "/docs/17/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/17/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=17", "label": "work_mem"}], "release": {"ref": "PostgreSQL 17.11 source archive", "label": "17.11", "major": "17", "channel": "stable", "revision": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979", "source_url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "line": 1427, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1427", "sha256": "741251b1a3b6d269a52a673d42eb63b02e13a5872db7b359b137086ab21b63c8", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "a77576e158b94cb01fa8c5174ba133004eabdd727660323f8afc66c8d2e757b8", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "f03122d0aba6181ea442d719d6ba99f851c5eefe4b9c255ecf1b1e3636e0efe1", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "d390dd69e2d3f5085beb42b33e46ff0676a2959b916a12b82118a7e545f8e562", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "0d4316ed2d09288c2e3be15be1ce01b88622354bcd571ac7ebc45aa9319b90e7", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002", "\u4f7f\u7528\u54c8\u5e0c\u65f6\uff0c\u9700\u8981\u4e00\u4e2a\u7528\u4e8e\u6bd4\u8f83\u7684\u5143\u7ec4\u7ea7\u5185\u5b58\u4e0a\u4e0b\u6587\uff0c\u4ee5\u53ca\u4e00\u4e2a\u751f\u547d\u5468\u671f\u66f4\u957f\u3001\u7528\u4e8e\u5b58\u50a8\u54c8\u5e0c\u8868\u7684\u4e0a\u4e0b\u6587\u3002\u4e0d\u80fd\u76f4\u63a5\u5c06\u54c8\u5e0c\u8868\u4fdd\u5b58\u5728\u67e5\u8be2\u7ea7\u4e0a\u4e0b\u6587\u4e2d\uff0c\u56e0\u4e3a\u91cd\u626b\u65f6\u9700\u8981\u80fd\u4e22\u5f03\u5b83\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/17/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/17/facts/0/label": "Core node tag", "/versions/17/facts/1/label": "Structured EXPLAIN Node Type", "/versions/17/facts/2/label": "Inputs", "/versions/17/facts/2/value": "Non-recursive and recursive child plans", "/versions/17/facts/3/label": "Output", "/versions/17/facts/3/value": "Recursive query tuples", "/versions/17/facts/4/label": "Executor initializer", "/versions/17/facts/5/label": "Memory mechanism", "/versions/17/tables/0/title": "EXPLAIN labels in this source build", "/versions/17/related/1/label": "Using EXPLAIN", "/versions/17/related/2/label": "Parallel plans", "/versions/17/sections/0/title": "EXPLAIN names and attributes", "/versions/17/sections/1/title": "Memory and temporary storage", "/versions/17/sections/2/title": "Parallel execution and instrumentation", "/versions/17/sections/3/title": "Executor implementation notes", "/versions/17/sections/4/title": "EXPLAIN identity in core source", "/versions/17/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/17/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/17/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/17/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/17/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/17/sections/2/paragraphs/0": "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.", "/versions/17/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/17/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/17/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/17/sections/3/paragraphs/2": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/17/sections/3/paragraphs/3": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/17/sections/3/paragraphs/4": "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning.", "/versions/17/tables/0/columns/0/label": "Text-format label", "/versions/17/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "5aace75746b6b55ab5122263757d29c9a1bf9fee34323096abe5aa53dfa338ea"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "18": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "315c2d4d0a7a1ddf362ad19357cb62c7615592d2f51aaee87d313b4fe0d9536a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "27a85416bafed557006c705ab5d0c5dce3d3c1702812bb54d136f2ac4c41055a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=18", "label": "EXPLAIN"}, {"url": "/docs/18/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/18/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=18", "label": "work_mem"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 1412, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1412", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "315c2d4d0a7a1ddf362ad19357cb62c7615592d2f51aaee87d313b4fe0d9536a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "27a85416bafed557006c705ab5d0c5dce3d3c1702812bb54d136f2ac4c41055a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u5982\u679c\u4e24\u4e2a\u5b50\u8ba1\u5212\u63d0\u4f9b\u76f8\u540c\u4e14\u56fa\u5b9a\u7684\u5143\u7ec4\u69fd\u7c7b\u578b\uff0c\u5c31\u53ef\u4ee5\u544a\u77e5 BuildTupleHashTable \u5c06\u6b64\u7c7b\u578b\u4f5c\u4e3a\u9884\u671f\u8f93\u5165\uff1b\u5426\u5219\u4f20\u5165 NULL\uff0c\u8868\u793a\u53ef\u80fd\u51fa\u73b0\u4efb\u610f\u69fd\u7c7b\u578b\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/18/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/18/facts/0/label": "Core node tag", "/versions/18/facts/1/label": "Structured EXPLAIN Node Type", "/versions/18/facts/2/label": "Inputs", "/versions/18/facts/2/value": "Non-recursive and recursive child plans", "/versions/18/facts/3/label": "Output", "/versions/18/facts/3/value": "Recursive query tuples", "/versions/18/facts/4/label": "Executor initializer", "/versions/18/facts/5/label": "Memory mechanism", "/versions/18/tables/0/title": "EXPLAIN labels in this source build", "/versions/18/related/1/label": "Using EXPLAIN", "/versions/18/related/2/label": "Parallel plans", "/versions/18/sections/0/title": "EXPLAIN names and attributes", "/versions/18/sections/1/title": "Memory and temporary storage", "/versions/18/sections/2/title": "Parallel execution and instrumentation", "/versions/18/sections/3/title": "Executor implementation notes", "/versions/18/sections/4/title": "EXPLAIN identity in core source", "/versions/18/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/18/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/18/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/18/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/18/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/18/sections/2/paragraphs/0": "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.", "/versions/18/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/18/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/18/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/18/sections/3/paragraphs/2": "If both child plans deliver the same fixed tuple slot type, we can tell BuildTupleHashTable to expect that slot type as input. Otherwise, we'll pass NULL denoting that any slot type is possible.", "/versions/18/sections/3/paragraphs/3": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/18/sections/3/paragraphs/4": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/18/tables/0/columns/0/label": "Text-format label", "/versions/18/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "74eef3e9b5f10ae5c601987a20231a87f4b8dbec6c922039db53ccad9c3c4b84"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "19": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "cbf92a385bb3319cba428433949e6a53d240a6ea67faa183a318d31313737c4b", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "cda3af245b88d079a32616b4cc5316913d349ba3acaab5fc1fd8aec479cc51ee", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=19", "label": "EXPLAIN"}, {"url": "/docs/19/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/19/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=19", "label": "work_mem"}], "release": {"ref": "PostgreSQL 19beta4 source archive", "label": "19beta4", "major": "19", "channel": "preview", "revision": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86", "source_url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "line": 1424, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1424", "sha256": "8b115b1c194a4b54ae630209a741e293b1df49a9052f10b2de9ca092a48998e3", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "5e39b2037bed672da55104229ecc32da5abde44c26bcad01479edcfa044d09ed", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "cbf92a385bb3319cba428433949e6a53d240a6ea67faa183a318d31313737c4b", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "1c65d5d6b6c81c71531685843647869bcae630779d815a5036b06e070c6c06c7", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "cda3af245b88d079a32616b4cc5316913d349ba3acaab5fc1fd8aec479cc51ee", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u5982\u679c\u4e24\u4e2a\u5b50\u8ba1\u5212\u63d0\u4f9b\u76f8\u540c\u4e14\u56fa\u5b9a\u7684\u5143\u7ec4\u69fd\u7c7b\u578b\uff0c\u5c31\u53ef\u4ee5\u544a\u77e5 BuildTupleHashTable \u5c06\u6b64\u7c7b\u578b\u4f5c\u4e3a\u9884\u671f\u8f93\u5165\uff1b\u5426\u5219\u4f20\u5165 NULL\uff0c\u8868\u793a\u53ef\u80fd\u51fa\u73b0\u4efb\u610f\u69fd\u7c7b\u578b\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/19/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/19/facts/0/label": "Core node tag", "/versions/19/facts/1/label": "Structured EXPLAIN Node Type", "/versions/19/facts/2/label": "Inputs", "/versions/19/facts/2/value": "Non-recursive and recursive child plans", "/versions/19/facts/3/label": "Output", "/versions/19/facts/3/value": "Recursive query tuples", "/versions/19/facts/4/label": "Executor initializer", "/versions/19/facts/5/label": "Memory mechanism", "/versions/19/tables/0/title": "EXPLAIN labels in this source build", "/versions/19/related/1/label": "Using EXPLAIN", "/versions/19/related/2/label": "Parallel plans", "/versions/19/sections/0/title": "EXPLAIN names and attributes", "/versions/19/sections/1/title": "Memory and temporary storage", "/versions/19/sections/2/title": "Parallel execution and instrumentation", "/versions/19/sections/3/title": "Executor implementation notes", "/versions/19/sections/4/title": "EXPLAIN identity in core source", "/versions/19/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/19/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/19/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/19/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/19/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/19/sections/2/paragraphs/0": "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.", "/versions/19/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/19/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/19/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/19/sections/3/paragraphs/2": "If both child plans deliver the same fixed tuple slot type, we can tell BuildTupleHashTable to expect that slot type as input. Otherwise, we'll pass NULL denoting that any slot type is possible.", "/versions/19/sections/3/paragraphs/3": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/19/sections/3/paragraphs/4": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/19/tables/0/columns/0/label": "Text-format label", "/versions/19/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "badd7e459d0da6eb8621ad2ad6ff39dad706a9ba37e7e6ec9decd6051b6928b0"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "20": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "cbf92a385bb3319cba428433949e6a53d240a6ea67faa183a318d31313737c4b", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "46a50e4790274348dfdc6e24f63ae12809d38e639d19378c01d6daff55e61644", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=20", "label": "EXPLAIN"}, {"url": "/docs/devel/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/devel/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=20", "label": "work_mem"}], "release": {"ref": "PostgreSQL 20devel source archive", "label": "20devel", "major": "20", "channel": "devel", "revision": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41", "source_url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "source_snapshot_utc": "26-Sep-2026 20:22"}, "sources": [{"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "line": 1424, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1424", "sha256": "13402758013520451539427b5993db06d463ca11c4e2d4cc5444e82367688077", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "5e39b2037bed672da55104229ecc32da5abde44c26bcad01479edcfa044d09ed", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "cbf92a385bb3319cba428433949e6a53d240a6ea67faa183a318d31313737c4b", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "7a94ed1652f0d74d50c39971d1cd3e8051dbc0d6058f31b6de71a433ca343521", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "46a50e4790274348dfdc6e24f63ae12809d38e639d19378c01d6daff55e61644", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u5982\u679c\u4e24\u4e2a\u5b50\u8ba1\u5212\u63d0\u4f9b\u76f8\u540c\u4e14\u56fa\u5b9a\u7684\u5143\u7ec4\u69fd\u7c7b\u578b\uff0c\u5c31\u53ef\u4ee5\u544a\u77e5 BuildTupleHashTable \u5c06\u6b64\u7c7b\u578b\u4f5c\u4e3a\u9884\u671f\u8f93\u5165\uff1b\u5426\u5219\u4f20\u5165 NULL\uff0c\u8868\u793a\u53ef\u80fd\u51fa\u73b0\u4efb\u610f\u69fd\u7c7b\u578b\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/summary": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/category": "Combination", "/versions/20/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/20/facts/0/label": "Core node tag", "/versions/20/facts/1/label": "Structured EXPLAIN Node Type", "/versions/20/facts/2/label": "Inputs", "/versions/20/facts/2/value": "Non-recursive and recursive child plans", "/versions/20/facts/3/label": "Output", "/versions/20/facts/3/value": "Recursive query tuples", "/versions/20/facts/4/label": "Executor initializer", "/versions/20/facts/5/label": "Memory mechanism", "/versions/20/tables/0/title": "EXPLAIN labels in this source build", "/versions/20/related/1/label": "Using EXPLAIN", "/versions/20/related/2/label": "Parallel plans", "/versions/20/sections/0/title": "EXPLAIN names and attributes", "/versions/20/sections/1/title": "Memory and temporary storage", "/versions/20/sections/2/title": "Parallel execution and instrumentation", "/versions/20/sections/3/title": "Executor implementation notes", "/versions/20/sections/4/title": "EXPLAIN identity in core source", "/versions/20/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/20/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/20/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/20/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/20/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/20/sections/2/paragraphs/0": "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.", "/versions/20/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/20/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/20/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/20/sections/3/paragraphs/2": "If both child plans deliver the same fixed tuple slot type, we can tell BuildTupleHashTable to expect that slot type as input. Otherwise, we'll pass NULL denoting that any slot type is possible.", "/versions/20/sections/3/paragraphs/3": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/20/sections/3/paragraphs/4": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/20/tables/0/columns/0/label": "Text-format label", "/versions/20/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "db51c3d2a8e7e3d3b0ff7393f5ccb4cdf4ad02ffa40a5c50c999ad3a518c3e09"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}}}, "snapshot": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_RecursiveUnion"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Recursive Union"}, {"label": "\u8f93\u5165", "value": "\u975e\u9012\u5f52\u548c\u9012\u5f52\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u9012\u5f52\u67e5\u8be2\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitRecursiveUnion"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "315c2d4d0a7a1ddf362ad19357cb62c7615592d2f51aaee87d313b4fe0d9536a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "27a85416bafed557006c705ab5d0c5dce3d3c1702812bb54d136f2ac4c41055a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "mechanism": "tuplestore", "description": "\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=18", "label": "EXPLAIN"}, {"url": "/docs/18/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/18/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/work_mem/?v=18", "label": "work_mem"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 1412, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1412", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "315c2d4d0a7a1ddf362ad19357cb62c7615592d2f51aaee87d313b4fe0d9536a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "27a85416bafed557006c705ab5d0c5dce3d3c1702812bb54d136f2ac4c41055a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aRecursive Union.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u4f7f\u7528 work_mem \u521b\u5efa tuplestore\u3002tuplestore \u53ef\u4ee5\u5c06\u5b58\u50a8\u7684\u5143\u7ec4\u79fb\u5230\u4e34\u65f6\u6587\u4ef6\uff0c\u4f46\u8fd9\u4e0d\u610f\u5473\u7740 work_mem \u9650\u5236\u4e86\u8282\u70b9\u7684\u5168\u90e8\u5185\u5b58\u5206\u914d\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1anone extracted from this node implementation."]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeRecursiveunion.c\uff1a\u5904\u7406 RecursiveUnion \u8282\u70b9\u7684\u4f8b\u7a0b\u3002", "\u4e3a\u5b9e\u73b0\u4e0d\u5e26 ALL \u7684 UNION\uff0c\u9700\u8981\u7528\u54c8\u5e0c\u8868\u4fdd\u5b58\u5df2\u89c1\u8fc7\u7684\u5143\u7ec4\uff1b\u54c8\u5e0c\u952e\u7531\u5206\u7ec4\u5217\u8ba1\u7b97\u3002", "\u5982\u679c\u4e24\u4e2a\u5b50\u8ba1\u5212\u63d0\u4f9b\u76f8\u540c\u4e14\u56fa\u5b9a\u7684\u5143\u7ec4\u69fd\u7c7b\u578b\uff0c\u5c31\u53ef\u4ee5\u544a\u77e5 BuildTupleHashTable \u5c06\u6b64\u7c7b\u578b\u4f5c\u4e3a\u9884\u671f\u8f93\u5165\uff1b\u5426\u5219\u4f20\u5165 NULL\uff0c\u8868\u793a\u53ef\u80fd\u51fa\u73b0\u4efb\u610f\u69fd\u7c7b\u578b\u3002", "\u987a\u5e8f\u626b\u63cf\u9012\u5f52\u67e5\u8be2\u5e76\u8fd4\u56de\u4e0b\u4e00\u4e2a\u6ee1\u8db3\u6761\u4ef6\u7684\u5143\u7ec4\u3002", "2.1 WT := RT\u30022.2 \u5f53 WT \u975e\u7a7a\u65f6\uff0c\u91cd\u590d 2.3 \u81f3 2.6\uff1bWT \u4e3a\u7a7a\u65f6\u8fd4\u56de RT\u30022.3 \u7528 WT \u66ff\u6362\u9012\u5f52\u9879\u540d\u79f0\u30022.4 \u6c42\u503c\u9012\u5f52\u9879\u5e76\u5b58\u5165 WT\u30022.5 \u5c06 WT \u8ffd\u52a0\u5230 RT\u30022.6 \u8f6c\u5230 2.2\u3002"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u4f7f\u7528\u5de5\u4f5c\u8868\u548c\u4e2d\u95f4\u8868\u6267\u884c\u9012\u5f52\u8054\u5408\u7684\u975e\u9012\u5f52\u9879\u4e0e\u9012\u5f52\u9879\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/18/description/0": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "/versions/18/facts/0/label": "Core node tag", "/versions/18/facts/1/label": "Structured EXPLAIN Node Type", "/versions/18/facts/2/label": "Inputs", "/versions/18/facts/2/value": "Non-recursive and recursive child plans", "/versions/18/facts/3/label": "Output", "/versions/18/facts/3/value": "Recursive query tuples", "/versions/18/facts/4/label": "Executor initializer", "/versions/18/facts/5/label": "Memory mechanism", "/versions/18/tables/0/title": "EXPLAIN labels in this source build", "/versions/18/related/1/label": "Using EXPLAIN", "/versions/18/related/2/label": "Parallel plans", "/versions/18/sections/0/title": "EXPLAIN names and attributes", "/versions/18/sections/1/title": "Memory and temporary storage", "/versions/18/sections/2/title": "Parallel execution and instrumentation", "/versions/18/sections/3/title": "Executor implementation notes", "/versions/18/sections/4/title": "EXPLAIN identity in core source", "/versions/18/memory/description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/18/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/18/sections/0/paragraphs/1": "Text names recorded by this source: Recursive Union.", "/versions/18/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/18/sections/1/paragraphs/0": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "/versions/18/sections/2/paragraphs/0": "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.", "/versions/18/sections/2/paragraphs/1": "Callbacks in this build: none extracted from this node implementation.", "/versions/18/sections/3/paragraphs/0": "nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "/versions/18/sections/3/paragraphs/1": "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "/versions/18/sections/3/paragraphs/2": "If both child plans deliver the same fixed tuple slot type, we can tell BuildTupleHashTable to expect that slot type as input. Otherwise, we'll pass NULL denoting that any slot type is possible.", "/versions/18/sections/3/paragraphs/3": "Scans the recursive query sequentially and returns the next qualifying tuple.", "/versions/18/sections/3/paragraphs/4": "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "/versions/18/tables/0/columns/0/label": "Text-format label", "/versions/18/tables/0/columns/1/label": "Structured node identity"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "74eef3e9b5f10ae5c601987a20231a87f4b8dbec6c922039db53ccad9c3c4b84"}, "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "comparison": {"left": "17", "right": "18", "status": "unchanged", "diff": ""}}