↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

百科 / 外部数据包装器 / 远程 PostgreSQL

postgres_fdw

Remote PostgreSQL

postgres_fdw 模块提供外部数据包装器 postgres_fdw ,可用于访问存储在外部 PostgreSQL 服务器中的数据。 本模块提供的功能与较旧的 dblink 模块在很大程度上重叠。但 postgres_fdw 为访问远程表提供了更透明且符合标准的语法,并且在许多情况下性能更好。 要准备通过 postgres_fdw 进行远程访问: 现在,只需对外部表执行 SELECT ,即可访问其底层远程表中存储的数据。也可以使用 INSERT 、 UPDATE 、 DELETE 、 C…

当前查看 PostgreSQL 18。

中文定义与说明

外部数据包装器 postgres_fdw。

同版本中文手册节选

postgres_fdw 模块提供外部数据包装器 postgres_fdw,可用于访问存储在外部 PostgreSQL 服务器中的数据。

本模块提供的功能与较旧的 dblink 模块在很大程度上重叠。但 postgres_fdw 为访问远程表提供了更透明且符合标准的语法,并且在许多情况下性能更好。

要准备通过 postgres_fdw 进行远程访问:

现在,只需对外部表执行 SELECT,即可访问其底层远程表中存储的数据。也可以使用 INSERT、UPDATE、DELETE、COPY 或 TRUNCATE 修改远程表。(当然,在用户映射中指定的远程用户必须拥有执行这些操作的权限。)

查看完整中文手册与上下文。

说明

postgres_fdw 模块提供外部数据包装器 postgres_fdw ,可用于访问存储在外部 PostgreSQL 服务器中的数据。 本模块提供的功能与较旧的 dblink 模块在很大程度上重叠。但 postgres_fdw 为访问远程表提供了更透明且符合标准的语法,并且在许多情况下性能更好。 要准备通过 postgres_fdw 进行远程访问: 现在,只需对外部表执行 SELECT ,即可访问其底层远程表中存储的数据。也可以使用 INSERT 、 UPDATE 、 DELETE 、 COPY 或 TRUNCATE 修改远程表。(当然,在用户映射中指定的远程用户必须拥有执行这些操作的权限。)

接口类别
外部数据包装器
处理函数或例程
postgres_fdw_handler
记录的回调
36
数据源
远程 PostgreSQL 服务器

接口与能力边界

矩阵记录此源码构建实际注册的回调。注册表明实现了相应接口钩子;操作是否允许还取决于选项、查询形式、权限和提供方规则。

下方保留同版本完整手册,包括配置、约束和示例。不声称已进行运行时能力测试。

异步执行选项

postgres_fdw 支持异步执行,它可以并发运行 Append 节点的多个部分,而不是串行运行,以提高性能。可以使用以下选项控制这种执行方式:

事务管理选项

如“事务管理”一节所述,在 postgres_fdw 中,事务是通过创建对应的远程事务来管理的,子事务则通过创建对应的远程子事务来管理。当当前本地事务涉及多个远程事务时,默认情况下, postgres_fdw 会在本地事务提交或中止时串行提交或中止这些远程事务。当当前本地子事务涉及多个远程子事务时,默认情况下, postgres_fdw 也会在本地子事务提交或中止时串行提交或中止这些远程子事务。使用以下选项可以改善性能:

如果启用了这些选项的多个外部服务器参与同一个本地事务,那么在本地事务提交或中止时,这些外部服务器上的多个远程事务会跨服务器并行提交或中止。

启用这些选项后,若某个外部服务器涉及很多远程事务,则在本地事务提交或中止时,该外部服务器上的性能可能会受到负面影响。

事务管理

在引用某个外部服务器上任意远程表的查询期间,如果当前本地事务尚未在该远程服务器上打开对应的事务, postgres_fdw 就会在该远程服务器上打开一个事务。本地事务提交或中止时,远程事务也会提交或中止。保存点也会通过创建对应的远程保存点进行类似管理。

当本地事务的隔离级别为 SERIALIZABLE 时,远程事务使用 SERIALIZABLE ;否则使用 REPEATABLE READ 隔离级别。这一选择确保如果一个查询在远程服务器上执行多次表扫描,所有扫描都能获得快照一致的结果。其结果是,同一事务中的后续查询会看到来自远程服务器的相同数据,即使远程服务器由于其他活动正在发生并发更新。对于使用 SERIALIZABLE 或 REPEATABLE READ 隔离级别的本地事务,这种行为本来就符合预期;但对于 READ COMMITTED 本地事务,则可能令人意外。未来的 PostgreSQL 版本可能会修改这些规则。

请注意, postgres_fdw 当前不支持为两阶段提交预备远程事务。

远程查询优化

postgres_fdw 会尽力优化远程查询,以减少从外部服务器传输的数据量。这是通过将查询的 WHERE 子句发送到远程服务器执行,以及不获取当前查询不需要的表列来实现的。为降低查询被错误执行的风险,只有当 WHERE 子句使用的所有数据类型、操作符和函数都是内置的,或属于外部服务器 extensions 选项列出的扩展时,才会将该子句发送到远程服务器。这类子句中的操作符和函数还必须是 IMMUTABLE 。对于 UPDATE 或 DELETE 查询, postgres_fdw 会在查询中不存在无法发送到远程服务器的 WHERE 子句、没有本地连接操作、目标表上没有行级本地 BEFORE 或 AFTER 触发器或存储生成列,也没有来自父视图的 CHECK OPTION 约束时,尝试将整个查询发送到远程服务器以优化执行。在 UPDATE 中,为了降低查询被错误执行的风险,赋给目标列的表达式也必须只使用内置数据类型、 IMMUTABLE 操作符或 IMMUTABLE 函数。

当 postgres_fdw 遇到同一外部服务器上的外部表之间的连接时,除非由于某种原因它认为分别从各表取回行会更高效,或者相关表引用受不同用户映射约束,否则会将整个连接发送到远程服务器。在发送 JOIN 子句时,它也会采取与前述 WHERE 子句相同的预防措施。

可以使用 EXPLAIN VERBOSE 查看实际发送给远程服务器执行的查询。

跨版本兼容性

postgres_fdw 可用于访问 PostgreSQL 8.3 及更新的远程服务器;只读能力可追溯到 8.1。

一个限制是,postgres_fdw 通常认为外部表 WHERE 子句中的不可变内置函数和运算符可以安全地发送到远程服务器执行。因此,远程服务器所用版本之后才加入的内置函数也可能被发送过去,导致“function does not exist”或类似错误。可以通过改写查询绕过此问题,例如将外部表引用放入带 OFFSET 0 的子 SELECT 中,以此形成优化屏障,并将有问题的函数或运算符放在子 SELECT 外部。

另一个限制是,在外部表上执行 INSERT 语句并带有 ON CONFLICT DO NOTHING 子句时,远程服务器必须运行 PostgreSQL 9.5 或更高版本,因为更早版本不支持此特性。

核心源码中注册的实现

{
	FdwRoutine *routine = makeNode(FdwRoutine);

	/* Functions for scanning foreign tables */
	routine->GetForeignRelSize = postgresGetForeignRelSize;
	routine->GetForeignPaths = postgresGetForeignPaths;
	routine->GetForeignPlan = postgresGetForeignPlan;
	routine->BeginForeignScan = postgresBeginForeignScan;
	routine->IterateForeignScan = postgresIterateForeignScan;
	routine->ReScanForeignScan = postgresReScanForeignScan;
	routine->EndForeignScan = postgresEndForeignScan;

	/* Functions for updating foreign tables */
	routine->AddForeignUpdateTargets = postgresAddForeignUpdateTargets;
	routine->PlanForeignModify = postgresPlanForeignModify;
	routine->BeginForeignModify = postgresBeginForeignModify;
	routine->ExecForeignInsert = postgresExecForeignInsert;
	routine->ExecForeignBatchInsert = postgresExecForeignBatchInsert;
	routine->GetForeignModifyBatchSize = postgresGetForeignModifyBatchSize;
	routine->ExecForeignUpdate = postgresExecForeignUpdate;
	routine->ExecForeignDelete = postgresExecForeignDelete;
	routine->EndForeignModify = postgresEndForeignModify;
	routine->BeginForeignInsert = postgresBeginForeignInsert;
	routine->EndForeignInsert = postgresEndForeignInsert;
	routine->IsForeignRelUpdatable = postgresIsForeignRelUpdatable;
	routine->PlanDirectModify = postgresPlanDirectModify;
	routine->BeginDirectModify = postgresBeginDirectModify;
	routine->IterateDirectModify = postgresIterateDirectModify;
	routine->EndDirectModify = postgresEndDirectModify;

	/* Function for EvalPlanQual rechecks */
	routine->RecheckForeignScan = postgresRecheckForeignScan;
	/* Support functions for EXPLAIN */
	routine->ExplainForeignScan = postgresExplainForeignScan;
	routine->ExplainForeignModify = postgresExplainForeignModify;
	routine->ExplainDirectModify = postgresExplainDirectModify;

	/* Support function for TRUNCATE */
	routine->ExecForeignTruncate = postgresExecForeignTruncate;

	/* Support functions for ANALYZE */
	routine->AnalyzeForeignTable = postgresAnalyzeForeignTable;

	/* Support functions for IMPORT FOREIGN SCHEMA */
	routine->ImportForeignSchema = postgresImportForeignSchema;

	/* Support functions for join push-down */
	routine->GetForeignJoinPaths = postgresGetForeignJoinPaths;

	/* Support functions for upper relation push-down */
	routine->GetForeignUpperPaths = postgresGetForeignUpperPaths;

	/* Support functions for asynchronous execution */
	routine->IsForeignPathAsyncCapable = postgresIsForeignPathAsyncCapable;
	routine->ForeignAsyncRequest = postgresForeignAsyncRequest;
	routine->ForeignAsyncConfigureWait = postgresForeignAsyncConfigureWait;
	routine->ForeignAsyncNotify = postgresForeignAsyncNotify;

	PG_RETURN_POINTER(routine);
}

注册的接口处理函数

接口操作源码观察回调实现
扫描数据行已注册处理函数;适用条件限制IterateForeignScanpostgresIterateForeignScan
INSERT已注册处理函数;适用条件限制ExecForeignInsertpostgresExecForeignInsert
UPDATE已注册处理函数;适用条件限制ExecForeignUpdatepostgresExecForeignUpdate
DELETE已注册处理函数;适用条件限制ExecForeignDeletepostgresExecForeignDelete
TRUNCATE已注册处理函数;适用条件限制ExecForeignTruncatepostgresExecForeignTruncate
连接路径下推已注册处理函数;适用条件限制GetForeignJoinPathspostgresGetForeignJoinPaths
上层路径,包括聚合已注册处理函数;适用条件限制GetForeignUpperPathspostgresGetForeignUpperPaths
批量插入已注册处理函数;适用条件限制ExecForeignBatchInsertpostgresExecForeignBatchInsert
异步追加执行已注册处理函数;适用条件限制ForeignAsyncRequestpostgresForeignAsyncRequest
导入模式已注册处理函数;适用条件限制ImportForeignSchemapostgresImportForeignSchema

手册中的选项

选项同版本定义
schema_name该选项可为外部表指定,用于给出在远程服务器上为该外部表使用的模式名。如果省略,则使用外部表自身所在模式的名称。
table_name该选项可为外部表指定,用于给出在远程服务器上为该外部表使用的表名。如果省略,则使用外部表自身的名称。
column_name该选项可为外部表的某个列指定,用于给出在远程服务器上为该列使用的列名。如果省略,则使用该列自身的名称。
use_remote_estimate该选项可为外部表或外部服务器指定,用于控制 postgres_fdw 是否发出远程 EXPLAIN 命令来获取代价估算。外部表上的设置会覆盖其所属服务器的设置,但只对该表生效。默认值为 false 。
fdw_startup_cost该选项可为外部服务器指定,是一个浮点值,会被加到该服务器上任何外部表扫描的估计启动代价中。它表示建立连接、在远程端解析并规划查询等额外开销。默认值为 100 。
fdw_tuple_cost该选项可为外部服务器指定,是一个浮点值,用作该服务器上外部表扫描的每个元组的额外代价。它表示服务器之间数据传输的额外开销。可以增大或减小该数值,以反映到远程服务器更高或更低的网络延迟。默认值为 0.2 。
analyze_sampling此选项可在外部表或外部服务器上设置,决定外部表 ANALYZE 是在远程采样,还是读取并传输全部数据后在本地采样。支持 off、random、system、bernoulli 和 auto。off 禁用远程采样,全部数据会传到本地后采样。random 使用 random() 函数在远程选择返回行;system 和 bernoulli 使用同名内置 TABLESAMPLE 方法。random 适用于所有远程服务器版本,TABLESAMPLE 仅从 9.5 起支持。默认值 auto 自动选择推荐方法,目前根据远程服务器版本选择 bernoulli 或 random。
extensions该选项是一个以逗号分隔的 PostgreSQL 扩展名称列表,这些扩展必须在本地和远程服务器上都已安装且版本兼容。属于列出扩展且不可变的函数和操作符,将被视为可下推到远程服务器执行。该选项只能为外部服务器指定,不能按表指定。 使用 extensions 选项时, 确保所列扩展在本地和远程服务器上都存在且行为完全一致,属于用户自己的责任 。否则,远程查询可能失败或出现意外行为。
fetch_size该选项指定 postgres_fdw 在每次取回操作中应获取的行数。它可为外部表或外部服务器指定。表上指定的选项会覆盖服务器上指定的选项。默认值为 100 。
batch_size此选项指定 postgres_fdw 每次插入操作应插入的行数,可在外部表或外部服务器上设置,表级设置覆盖服务器级设置,默认值为 1。实际一次插入的行数取决于列数和 batch_size。一个批次作为一条查询执行,而 postgres_fdw 用于连接远程服务器的 libpq 协议将单条查询的参数数限制为 65535。当列数乘以 batch_size 超出限制时,会调整 batch_size 以避免报错。此选项也适用于向外部表执行 COPY,实际一次复制的行数按类似方式确定,但受 COPY 实现限制,最多为 1000 行。
async_capable该选项控制 postgres_fdw 是否允许为异步执行而并发扫描外部表。它可为外部表或外部服务器指定。表级选项会覆盖服务器级选项。默认值为 false 。 为了确保从外部服务器返回的数据保持一致,除非这些表使用不同的用户映射,否则对于同一外部服务器, postgres_fdw 只会打开一个连接,并且即使涉及多个外部表,也会顺序运行针对该服务器的所有查询。在这种情况下,禁用此选项以消除异步运行查询带来的开销,反而可能具有更好的性能。 即使 Append 节点同时包含同步执行和异步执行的子计划,也会应用异步执行。在这种情况下,如果异步子计划是使用 postgres_fdw 处理的,则在至少有一个同步子计划返回全部元组之前,不会返回异步子计划的元组,因为同步子计划执行时,异步子计划仍在等待发送给外部服务器的异步查询结果。这种行为在未来版本中可能会改变。
parallel_commit该选项控制在本地事务提交时, postgres_fdw 是否并行提交该本地事务中在某个外部服务器上打开的远程事务。此设置也适用于远程子事务和本地子事务。该选项只能为外部服务器指定,不能按表指定。默认值为 false 。
parallel_abort该选项控制在本地事务中止时, postgres_fdw 是否并行中止该本地事务中在某个外部服务器上打开的远程事务。此设置也适用于远程子事务和本地子事务。该选项只能为外部服务器指定,不能按表指定。默认值为 false 。
updatable该选项控制 postgres_fdw 是否允许使用 INSERT 、 UPDATE 和 DELETE 命令修改外部表。它可为外部表或外部服务器指定。表级选项会覆盖服务器级选项。默认值为 true 。 当然,如果远程表实际上不可更新,最终仍会报错。该选项的主要作用是允许在本地直接抛出错误,而无需查询远程服务器。但请注意, information_schema 视图会根据该选项的设置,将 postgres_fdw 外部表报告为可更新(或不可更新),而不会对远程服务器进行任何检查。
truncatable该选项控制 postgres_fdw 是否允许使用 TRUNCATE 命令截断外部表。它可为外部表或外部服务器指定。表级选项会覆盖服务器级选项。默认值为 true 。 当然,如果远程表实际上不可截断,最终仍会报错。该选项的主要作用是允许在本地直接抛出错误,而无需查询远程服务器。
import_collate该选项控制从外部服务器导入的外部表定义中是否包含列的 COLLATE 选项。默认值为 true 。如果远程服务器的排序规则名称集合与本地服务器不同,则可能需要关闭此选项;如果远程服务器运行在不同操作系统上,这种情况尤其可能发生。不过,如果这样做,导入表列的排序规则就存在与底层数据不匹配的严重风险,从而导致查询行为异常。 即使将此参数设置为 true ,导入排序规则为远程服务器默认值的列仍可能有风险。这些列会以 COLLATE "default" 导入,这将选择本地服务器的默认排序规则,而它可能并不相同。
import_default该选项控制从外部服务器导入的外部表定义中是否包含列的 DEFAULT 表达式。默认值为 false 。如果启用此选项,需要警惕那些在本地服务器上的计算结果可能与远程服务器不同的默认值; nextval() 是常见的问题来源。如果导入的默认值表达式使用了本地不存在的函数或操作符,则整个 IMPORT 将失败。
import_generated该选项控制从外部服务器导入的外部表定义中是否包含列的 GENERATED 表达式。默认值为 true 。如果导入的生成表达式使用了本地不存在的函数或操作符,则整个 IMPORT 将失败。
import_not_null该选项控制从外部服务器导入的外部表定义中是否包含列的 NOT NULL 约束。默认值为 true 。
keep_connections该选项控制 postgres_fdw 是否保持与外部服务器的连接处于打开状态,以便后续查询重用它们。该选项只能为外部服务器指定。默认值为 on 。如果设置为 off ,则到该外部服务器的所有连接都会在每个事务结束时被丢弃。
use_scram_passthrough该选项控制 postgres_fdw 在连接到外部服务器时是否使用 SCRAM 透传认证。该选项可为外部服务器或用户映射指定。用户映射的设置会覆盖外部服务器的设置。使用 SCRAM 透传认证时, postgres_fdw 使用经 SCRAM Hash 处理的凭据,而不是明文用户密码连接远程服务器。这样可以避免在 PostgreSQL 系统目录中存储明文用户密码。 要使用 SCRAM 透传认证: 远程服务器必须请求 scram-sha-256 认证方法;否则连接将失败。 远程服务器可以是任何支持 SCRAM 的 PostgreSQL 版本。对 use_scram_passthrough 的支持只要求客户端一侧(FDW 侧)具备。 用户映射密码不会被使用。 运行 postgres_fdw 的服务器与远程服务器,必须针对用于在 postgres_fdw 上认证到外部服务器的该用户,拥有完全相同的 SCRAM 凭据(加密密码)(盐值和迭代次数都必须相同,而不仅仅是密码相同)。 因而,如果要建立到多个主机的 FDW 连接,例如用于分区外部表或分片,则所有主机都必须为相关用户保存完全相同的 SCRAM 凭据。 发起对外 FDW 连接的 PostgreSQL 实例中,当前会话的传入客户端连接也必须使用 SCRAM 认证。(因此称为 “ 透传 ” :SCRAM 必须在进入和离开时都被使用。)这是 SCRAM 协议的技术要求。

相关条目

文档与源码

来源构建
版本
18.6
构建
PostgreSQL 18.6 source archive
来源指纹
555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f

版本比较

PostgreSQL 11 → 12: 属性变化。

以下差异保留原始字段名与英文源描述。

--- PostgreSQL 11
+++ PostgreSQL 12
@@ -76,6 +76,10 @@
       "name": "import_default"
     },
     {
+      "definition": "This option controls whether column GENERATED expressions are included in the definitions of foreign tables imported from a foreign server. The default is true . The IMPORT will fail altogether if an imported generated expression uses a function or operator that does not exist locally.",
+      "name": "import_generated"
+    },
+    {
       "definition": "This option controls whether column NOT NULL constraints are included in the definitions of foreign tables imported from a foreign server. The default is true .",
       "name": "import_not_null"
     }

比较已记录的接口与属性,排除来源指纹和构建元数据。某个样本中没有记录,不能据此判断实际引入或移除的版本。

导出 JSON · 返回外部数据包装器 · 收录范围为 PostgreSQL 10 至 20;最早采样版本不一定是实际引入版本。