{"Entry":{"collection":"plan","key":"foreign-scan","name":"Foreign Scan","aliases":["Foreign Delete","Foreign Insert","Foreign Scan","Foreign Update","ForeignScan","T_ForeignScan"],"metadata":{"aliases":["Foreign Delete","Foreign Insert","Foreign Scan","Foreign Update","ForeignScan","T_ForeignScan"],"category":"Extensibility","content_hash":"e8a00b1256b63b1dbb9ad615be10919cbcedb8e05e607c6892c146112d2d2ab7","derived_content_hash":"6e76906b13ec5f079966f3fe6212dd621a2818fd5a8b6158a2f4d87c0c0a163c","imported_at":"2026-09-30T00:40:44.111867+08:00","name":"Foreign Scan","name_zh":"ForeignScan","slug":"foreign-scan","summary":"Delegates a foreign scan or supported direct modification to the foreign-data wrapper."}},"Definition":{"Collection":"plan","Key":"foreign-scan","SourceDatabase":"center","Version":"18","SourceTable":"plan_node","SourceKey":"foreign-scan","SourceRevision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","Facts":{"comparison_data":{"initializer":"ExecInitForeignScan","memory_mechanism":"unclassified","node_tag":"T_ForeignScan","parallel_callbacks":["ExecForeignScanEstimate","ExecForeignScanInitializeDSM","ExecForeignScanInitializeWorker","ExecForeignScanReInitializeDSM"],"partial_modes":[],"strategies":[],"text_names":["Foreign Scan","Foreign Insert","Foreign Update","Foreign Delete"]},"comparison_hash":"1c2fce5096a585774ac71065ed48f534475dbb94feb6a37eb58f5b2ea8f25ac5","description":["Delegates a foreign scan or supported direct modification to the foreign-data wrapper."],"description_zh":"将外部扫描或所支持的直接修改交给外部数据包装器执行。","description_zh_html":"\u003cp\u003e将外部扫描或所支持的直接修改交给外部数据包装器执行。\u003c/p\u003e\u003cp\u003e核心节点标识：\u003ccode\u003eT_ForeignScan\u003c/code\u003e；EXPLAIN 名称：\u003ccode\u003eForeign Scan, Foreign Insert, Foreign Update, Foreign Delete\u003c/code\u003e。\u003c/p\u003e\u003cp\u003e本版本源码中的并行执行或观测回调：\u003ccode\u003eExecForeignScanEstimate, ExecForeignScanInitializeDSM, ExecForeignScanInitializeWorker, ExecForeignScanReInitializeDSM\u003c/code\u003e。回调的存在不表示该节点必然支持共享并行扫描；在并行工作进程中执行也不等于具有并行感知能力。\u003c/p\u003e\u003ch3\u003e同版本中文手册节选\u003c/h3\u003e\u003cp\u003e\n\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e 会为收到的每个查询制定一个\u003cem class=\"firstterm\"\u003e查询计划\u003c/em\u003e。选择与查询结构和数据特性相匹配的正确计划，对获得良好的性能至关重要，因此系统内置了一个复杂的\u003cem class=\"firstterm\"\u003e规划器\u003c/em\u003e来尽量选出好的计划。可以使用 \u003ca class=\"link\" href=\"/zh/docs/18/sql-explain.html\"\u003e\u003ccode class=\"command\"\u003eEXPLAIN\u003c/code\u003e\u003c/a\u003e 命令查看规划器为任意查询生成的查询计划。读懂计划是一门需要经验积累的技能，本节将尝试介绍其中的基础知识。\n   \u003c/p\u003e\u003cp\u003e\n    本节中的示例取自执行过 \u003ccode class=\"command\"\u003eVACUUM ANALYZE\u003c/code\u003e 的回归测试数据库，使用的是 v18 开发版本源码。如果自行尝试这些示例，通常应当能得到相近的结果，但估计代价和行计数可能略有差异，因为 \u003ccode class=\"command\"\u003eANALYZE\u003c/code\u003e 生成的统计信息来自随机采样而非精确计数，而且代价本身在某种程度上也依赖于平台。\n   \u003c/p\u003e\u003cp\u003e\n    这些示例使用 \u003ccode class=\"command\"\u003eEXPLAIN\u003c/code\u003e 默认的\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003etext\u003c/span\u003e”\u003c/span\u003e输出格式，它紧凑且便于人工阅读。如果希望将 \u003ccode class=\"command\"\u003eEXPLAIN\u003c/code\u003e 的输出交给程序做进一步分析，则应改用机器可读的输出格式（XML、JSON 或 YAML）。\n   \u003c/p\u003e\u003cp\u003e\u003ca href=\"/zh/docs/18/using-explain.html\"\u003e查看完整中文手册与上下文\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e本页开头的中文说明为 PG.CENTER 对编辑说明的翻译；手册节选保留对应版本中文文档原文。源码信息及手册示例不代表重新进行过运行测试。\u003c/p\u003e","evidence_kind":"source and documentation","explain_names":["Foreign Scan","Foreign Insert","Foreign Update","Foreign Delete"],"explain_prefixes":["Parallel","Async"],"facts":[{"label":"Core node tag","value":"T_ForeignScan"},{"label":"Structured EXPLAIN Node Type","value":"Foreign Scan"},{"label":"Inputs","value":"Foreign-data wrapper plan and callbacks"},{"label":"Output","value":"Provider-defined scan or RETURNING tuples"},{"label":"Executor initializer","value":"ExecInitForeignScan"},{"label":"Memory mechanism","value":"unclassified"}],"facts_zh":[{"label":"核心节点标签","value":"T_ForeignScan"},{"label":"结构化 EXPLAIN 节点类型","value":"Foreign Scan"},{"label":"输入","value":"外部数据包装器计划及回调"},{"label":"输出","value":"提供方定义的扫描元组或 RETURNING 元组"},{"label":"执行器初始化函数","value":"ExecInitForeignScan"},{"label":"内存机制","value":"unclassified"}],"memory":{"description":"This extraction does not assign a universal memory limit or spill policy to this node. Inspect the same-build implementation and its expressions or provider.","evidence":[{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/nodeForeignscan.c","path":"src/backend/executor/nodeForeignscan.c","sha256":"37b85b68b6fc26d94e40d9173dbfed8b69c70877c54ee72ffc761e2f7b876a0c","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"}],"mechanism":"unclassified","source_notes":[]},"node_tag":"T_ForeignScan","parallel_callbacks":["ExecForeignScanEstimate","ExecForeignScanInitializeDSM","ExecForeignScanInitializeWorker","ExecForeignScanReInitializeDSM"],"partial_modes":[],"related":[{"label":"EXPLAIN","url":"/wiki/sql/explain/?v=18"},{"label":"Using EXPLAIN","url":"/docs/18/using-explain.html"},{"label":"Parallel plans","url":"/docs/18/parallel-plans.html"}],"release":{"channel":"stable","label":"18.6","major":"18","ref":"PostgreSQL 18.6 source archive","revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","source_snapshot_utc":"","source_url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},"runtime_verified":false,"sections":[{"paragraphs":["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.","Text names recorded by this source: Foreign Scan, Foreign Insert, Foreign Update, Foreign Delete.","Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."],"title":"EXPLAIN names and attributes"},{"paragraphs":["This extraction does not assign a universal memory limit or spill policy to this node. Inspect the same-build implementation and its expressions or provider."],"title":"Memory and temporary storage"},{"paragraphs":["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.","Callbacks in this build: ExecForeignScanEstimate, ExecForeignScanInitializeDSM, ExecForeignScanInitializeWorker, ExecForeignScanReInitializeDSM."],"title":"Parallel execution and instrumentation"},{"paragraphs":["nodeForeignscan.c Routines to support scans of foreign tables","ExecForeignScan scans a foreign table. ExecInitForeignScan creates and initializes state info. ExecReScanForeignScan rescans the foreign relation. ExecEndForeignScan releases any resources allocated.","direct modifications cannot be re-evaluated, so shouldn't get here during EvalPlanQual processing","Insert valid value into tableoid, the only actually-useful system column.","ForeignRecheck -- access method routine to recheck a tuple in EvalPlanQual"],"title":"Executor implementation notes"},{"code":"case T_ForeignScan:\n\t\t\tsname = \"Foreign Scan\";\n\t\t\tswitch (((ForeignScan *) plan)-\u003eoperation)\n\t\t\t{\n\t\t\t\tcase CMD_SELECT:\n\t\t\t\t\tpname = \"Foreign Scan\";\n\t\t\t\t\toperation = \"Select\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CMD_INSERT:\n\t\t\t\t\tpname = \"Foreign Insert\";\n\t\t\t\t\toperation = \"Insert\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CMD_UPDATE:\n\t\t\t\t\tpname = \"Foreign Update\";\n\t\t\t\t\toperation = \"Update\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CMD_DELETE:\n\t\t\t\t\tpname = \"Foreign Delete\";\n\t\t\t\t\toperation = \"Delete\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tpname = \"???\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;","title":"EXPLAIN identity in core source"}],"sections_zh":[{"paragraphs":["结构化格式使用上述 Node Type。文本格式名称还可能包含操作、策略、连接类型、扫描方向或聚合阶段属性。","此源码记录的文本名称：Foreign Scan, Foreign Insert, Foreign Update, Foreign Delete.","并行感知与并行安全是不同的计划属性。在并行工作进程内运行的节点不一定是并行感知节点。"],"title":"EXPLAIN 名称与属性"},{"paragraphs":["本次抽取不为此节点设定统一的内存上限或落盘策略。请查看同一构建的实现、相关表达式或提供方。"],"title":"内存与临时存储"},{"paragraphs":["以下源码回调可以协调执行或收集工作进程的测量数据。回调存在不代表该节点普遍支持共享并行扫描或共享状态。","此构建的回调：ExecForeignScanEstimate, ExecForeignScanInitializeDSM, ExecForeignScanInitializeWorker, ExecForeignScanReInitializeDSM."],"title":"并行执行与运行信息采集"},{"paragraphs":["nodeForeignscan.c：支持外部表扫描的例程。","ExecForeignScan 扫描外部表。ExecInitForeignScan 创建并初始化状态信息。ExecReScanForeignScan 重新扫描外部关系。ExecEndForeignScan 释放所有已分配的资源。","直接修改无法重新计算，因此 EvalPlanQual 处理期间不应到达此处。","向 tableoid 写入有效值；这是唯一实际有用的系统列。","ForeignRecheck：在 EvalPlanQual 中重新检查元组的访问方法例程。"],"title":"执行器实现说明"},{"code":"case T_ForeignScan:\n\t\t\tsname = \"Foreign Scan\";\n\t\t\tswitch (((ForeignScan *) plan)-\u003eoperation)\n\t\t\t{\n\t\t\t\tcase CMD_SELECT:\n\t\t\t\t\tpname = \"Foreign Scan\";\n\t\t\t\t\toperation = \"Select\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CMD_INSERT:\n\t\t\t\t\tpname = \"Foreign Insert\";\n\t\t\t\t\toperation = \"Insert\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CMD_UPDATE:\n\t\t\t\t\tpname = \"Foreign Update\";\n\t\t\t\t\toperation = \"Update\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CMD_DELETE:\n\t\t\t\t\tpname = \"Foreign Delete\";\n\t\t\t\t\toperation = \"Delete\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tpname = \"???\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;","title":"核心源码中的 EXPLAIN 标识"}],"source_inventory":{"executor":"src/backend/executor/execProcnode.c","explain":"src/backend/commands/explain.c","implementation":"src/backend/executor/nodeForeignscan.c"},"sources":[{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/commands/explain.c:1483","line":1483,"path":"src/backend/commands/explain.c","sha256":"34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/execProcnode.c:284","line":284,"path":"src/backend/executor/execProcnode.c","sha256":"f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/nodeForeignscan.c","path":"src/backend/executor/nodeForeignscan.c","sha256":"37b85b68b6fc26d94e40d9173dbfed8b69c70877c54ee72ffc761e2f7b876a0c","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/include/nodes/plannodes.h","path":"src/include/nodes/plannodes.h","sha256":"52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"}],"strategies":[],"tables":[{"columns":[{"key":"label","label":"Text-format label"},{"key":"identity","label":"Structured node identity"}],"key":"explain-labels","rows":[{"identity":"Foreign Scan","label":"Foreign Scan"},{"identity":"Foreign Scan","label":"Foreign Insert"},{"identity":"Foreign Scan","label":"Foreign Update"},{"identity":"Foreign Scan","label":"Foreign Delete"}],"title":"EXPLAIN labels in this source build"}],"tables_zh":[{"columns":[{"key":"label","label":"文本格式标签"},{"key":"identity","label":"结构化节点标识"}],"key":"explain-labels","rows":[{"identity":"Foreign Scan","label":"Foreign Scan"},{"identity":"Foreign Scan","label":"Foreign Insert"},{"identity":"Foreign Scan","label":"Foreign Update"},{"identity":"Foreign Scan","label":"Foreign Delete"}],"title":"本构建中的 EXPLAIN 标签"}],"zh_from":{"authored_translation":"authored-translation-of-reviewed-guidance","body_sha256":"bb48b1605b30fde4cdb5043bdd87e6af376047de0f25240778e6eef2ac1f6e57","kind":"same-version-chinese-manual-with-authored-translation-of-reviewed-guidance","manual":{"anchor":"","build_id":107,"extraction":"concept-introduction","fragment_sha256":"15fbdf84b8f499253ade4f4a5841de138619a9933b93cc241d431dbe922fa40c","locale":"zh-Hans","page_key":"using-explain.html","source_hash":"d2f749744b3ac5aa2eb0154f295e8163903cd20fcc130c74c6172cdf2ae3a9df","source_revision":"unknown:rendered-translation-baseline","translated_from_revision":null,"translation_revision":"git:b1b500221dbe5437cfca004d6b04d3f6e422765d;html-sha256:08e987a66af27b98444a8057c256314eafa13611a3fb9e888214fc436824244b","url":"/zh/docs/18/using-explain.html","version":"18"},"runtime_rerun":false,"source_facts_revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}},"ManualEvidence":{"release":{"channel":"stable","label":"18.6","major":"18","ref":"PostgreSQL 18.6 source archive","revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","source_snapshot_utc":"","source_url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},"sources":[{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/commands/explain.c:1483","line":1483,"path":"src/backend/commands/explain.c","sha256":"34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/execProcnode.c:284","line":284,"path":"src/backend/executor/execProcnode.c","sha256":"f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/nodeForeignscan.c","path":"src/backend/executor/nodeForeignscan.c","sha256":"37b85b68b6fc26d94e40d9173dbfed8b69c70877c54ee72ffc761e2f7b876a0c","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/include/nodes/plannodes.h","path":"src/include/nodes/plannodes.h","sha256":"52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"}]},"MeasuredEvidence":{"runtime_verified":false}},"Text":{"Collection":"plan","Key":"foreign-scan","SourceDatabase":"center","Version":"18","Locale":"en","Title":"Foreign Scan","Summary":"Delegates a foreign scan or supported direct modification to the foreign-data wrapper.","BodyHTML":"\u003cp\u003eDelegates a foreign scan or supported direct modification to the foreign-data wrapper.\u003c/p\u003e","SourceRevision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","ContentHash":"ffcc186fa8c11b89acdd311507f417a6ed018b969049d6f7e9d2b45713930006","Payload":{"description":["Delegates a foreign scan or supported direct modification to the foreign-data wrapper."],"related":[{"label":"EXPLAIN","url":"/wiki/sql/explain/?v=18"},{"label":"Using EXPLAIN","url":"/docs/18/using-explain.html"},{"label":"Parallel plans","url":"/docs/18/parallel-plans.html"}],"sections":[{"paragraphs":["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.","Text names recorded by this source: Foreign Scan, Foreign Insert, Foreign Update, Foreign Delete.","Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."],"title":"EXPLAIN names and attributes"},{"paragraphs":["This extraction does not assign a universal memory limit or spill policy to this node. Inspect the same-build implementation and its expressions or provider."],"title":"Memory and temporary storage"},{"paragraphs":["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.","Callbacks in this build: ExecForeignScanEstimate, ExecForeignScanInitializeDSM, ExecForeignScanInitializeWorker, ExecForeignScanReInitializeDSM."],"title":"Parallel execution and instrumentation"},{"paragraphs":["nodeForeignscan.c Routines to support scans of foreign tables","ExecForeignScan scans a foreign table. ExecInitForeignScan creates and initializes state info. ExecReScanForeignScan rescans the foreign relation. ExecEndForeignScan releases any resources allocated.","direct modifications cannot be re-evaluated, so shouldn't get here during EvalPlanQual processing","Insert valid value into tableoid, the only actually-useful system column.","ForeignRecheck -- access method routine to recheck a tuple in EvalPlanQual"],"title":"Executor implementation notes"},{"code":"case T_ForeignScan:\n\t\t\tsname = \"Foreign Scan\";\n\t\t\tswitch (((ForeignScan *) plan)-\u003eoperation)\n\t\t\t{\n\t\t\t\tcase CMD_SELECT:\n\t\t\t\t\tpname = \"Foreign Scan\";\n\t\t\t\t\toperation = \"Select\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CMD_INSERT:\n\t\t\t\t\tpname = \"Foreign Insert\";\n\t\t\t\t\toperation = \"Insert\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CMD_UPDATE:\n\t\t\t\t\tpname = \"Foreign Update\";\n\t\t\t\t\toperation = \"Update\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CMD_DELETE:\n\t\t\t\t\tpname = \"Foreign Delete\";\n\t\t\t\t\toperation = \"Delete\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tpname = \"???\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;","title":"EXPLAIN identity in core source"}],"tables":[{"columns":[{"key":"label","label":"Text-format label"},{"key":"identity","label":"Structured node identity"}],"key":"explain-labels","rows":[{"identity":"Foreign Scan","label":"Foreign Scan"},{"identity":"Foreign Scan","label":"Foreign Insert"},{"identity":"Foreign Scan","label":"Foreign Update"},{"identity":"Foreign Scan","label":"Foreign Delete"}],"title":"EXPLAIN labels in this source build"}]}},"RequestedLocale":"en","Fallback":false,"Versions":["10","11","12","13","14","15","16","17","18","19","20"],"Locales":["en","zh-Hans"],"Signatures":null,"Spellings":null,"SQLState":null,"Evidence":null}
