postgres_fdw 模块提供外部数据包装器 postgres_fdw,它可用于访问存储在外部 PostgreSQL 服务器中的数据。
该模块提供的功能与较老的 dblink 模块的功能有大量重叠。但 postgres_fdw 为访问远程表提供了更透明、更符合标准的语法,并且在许多情况下可以带来更好的性能。
使用 postgres_fdw 准备远程访问的步骤:
使用 CREATE EXTENSION 安装 postgres_fdw 扩展。
使用 CREATE SERVER 创建外部服务器对象,代表你想要连接的每个远程数据库。将除 user 与 password 之外的连接信息指定为服务器对象的选项。
使用 CREATE USER MAPPING 为每个要允许访问每个外部服务器的数据库用户创建一个用户映射。将要使用的远程用户名与密码指定为用户映射的 user 与 password 选项。
使用 CREATE FOREIGN TABLE 或 IMPORT FOREIGN SCHEMA 为要访问的每个远程表创建一个外表。外表的列必须与被引用的远程表相匹配。不过,如果在外表对象选项中指定了正确的远程名称,你可以使用不同于远程表名的表名和/或列名。
现在只需对某个外表执行 SELECT 即可访问存储在其底层远程表中的数据。你还可以使用 INSERT、UPDATE、DELETE、COPY 或 TRUNCATE 修改远程表。(当然,你在用户映射中指定的远程用户必须具有执行这些操作的特权。)
请注意,在 SELECT、UPDATE、DELETE 或 TRUNCATE 中指定的 ONLY 选项在访问或修改远程表时没有效果。
请注意,postgres_fdw 目前缺少对带 ON CONFLICT DO
UPDATE 子句的 INSERT 语句的支持。不过,只要省略了唯一索引推断规范,就支持 ON CONFLICT DO NOTHING 子句。另请注意,postgres_fdw 支持由在分区表上执行的 UPDATE 语句引发的行移动,但目前不处理以下情况:被选中接收被移动行的远程分区同时也是同一条命令中会在其他地方被更新的 UPDATE 目标分区。
通常建议外表的列以与远程表被引用列完全相同的数据类型以及排序规则(如果适用)声明。虽然 postgres_fdw 目前在按需执行数据类型转换方面相当宽容,但当类型或排序规则不匹配时,由于远程服务器对查询条件的解释与本地服务器不同,可能出现令人惊讶的语义异常。
请注意,外表可以声明为比其底层远程表更少的列或不同的列顺序。列与远程表的匹配按名称进行,与位置无关。
使用 postgres_fdw 外部数据包装器的外部服务器可以具有 libpq 在连接字符串中接受的相同选项(如 Section 32.1.2 所述),但以下选项不允许或被特殊处理:
user、password 与 sslpassword(改为在用户映射中指定,或使用服务文件)
client_encoding(会根据本地服务器编码自动设置)
application_name — 它可以出现在连接与 postgres_fdw.application_name 的任一处或两处。如果两处都存在,postgres_fdw.application_name 会覆盖连接设置。与 libpq 不同,postgres_fdw 允许 application_name 包含 “转义序列”。详情参见 postgres_fdw.application_name。
fallback_application_name(始终设为 postgres_fdw)
sslkey 与 sslcert — 它们可以出现在连接与用户映射的任一处或两处。如果两处都存在,用户映射设置覆盖连接设置。
只有超级用户可以创建或修改带 sslcert 或 sslkey 设置的用户映射。
非超级用户可以使用密码认证或 GSSAPI 委托凭证连接外部服务器,因此在需要密码认证的场合,请为属于非超级用户的用户映射指定 password 选项。
超级用户可以通过设置用户映射选项 password_required 'false' 在逐个用户映射的基础上覆盖这一检查,例如
ALTER USER MAPPING FOR some_non_superuser SERVER loopback_nopw OPTIONS (ADD password_required 'false');
为防止无特权用户利用 postgres 服务器运行所用的 unix 用户的认证权利提升为超级用户权利,只有超级用户可以在用户映射上设置该选项。
根据 CVE-2007-3278 与 CVE-2007-6601,需要小心确保这不会让被映射用户有能力以超级用户身份连接被映射的数据库。不要在 public 角色上设置 password_required=false。请记住,被映射用户可能使用 postgres 服务器运行所用的系统用户的 unix 主目录中的任何客户端证书、.pgpass、.pg_service.conf 等。(关于如何查找主目录的细节,请参见 Section 32.16。)它们还可以使用 peer 或 ident 认证等认证模式授予的任何信任关系。
这些选项可用于控制在发送到远程 PostgreSQL 服务器的 SQL 语句中使用的名称。当外表创建时的名称与底层远程表的名称不同时,就需要这些选项。
schema_name (string)该选项可为一个外表指定,给出该外表在远程服务器上使用的模式名。如果省略该选项,则使用外表所在模式的名称。
table_name (string)该选项可为一个外表指定,给出该外表在远程服务器上使用的表名。如果省略该选项,则使用外表的名称。
column_name (string)该选项可为外表的一个列指定,给出该列在远程服务器上使用的列名。如果省略该选项,则使用该列的名称。
postgres_fdw 通过对远程服务器执行查询来获取远程数据,因此理想情况下,扫描外表的估算代价应等于在远程服务器上完成的代价加上一些通信开销。获得这种估算最可靠的方式是询问远程服务器然后再加上一些开销 — 但对简单查询而言,为获得代价估算而执行一次额外的远程查询可能并不值得。因此 postgres_fdw 提供以下选项来控制代价估算的方式:
use_remote_estimate (boolean)
该选项可为外表或外部服务器指定,控制 postgres_fdw 是否发出远程 EXPLAIN 命令来获取代价估算。外表的设置只对该表覆盖其服务器的设置。默认值为 false。
fdw_startup_cost (floating point)
该选项可为外部服务器指定,是一个加到该服务器上任何外表扫描的估算启动代价上的浮点值。它代表建立连接、在远端解析与规划查询等带来的额外开销。默认值为 100。
fdw_tuple_cost (floating point)
该选项可为外部服务器指定,是一个用作该服务器上外表扫描每元组额外代价的浮点值。它代表服务器之间数据传输的额外开销。你可以增大或减小该数字以反映到远程服务器更高或更低的网络延迟。默认值为 0.2。
当 use_remote_estimate 为真时,postgres_fdw 从远程服务器获取行数与代价估算,然后把 fdw_startup_cost 与 fdw_tuple_cost 加到代价估算上。当 use_remote_estimate 为假时,postgres_fdw 执行本地行数与代价估算,然后把 fdw_startup_cost 与 fdw_tuple_cost 加到代价估算上。除非远程表统计信息的本地副本可用,否则这种本地估算不太可能非常准确。在外表上运行 ANALYZE 是更新本地统计信息的方法;它会扫描远程表,然后像该表是本地表一样计算并存储统计信息。保留本地统计信息可以是降低远程表每查询规划开销的有用手段 — 但如果远程表频繁更新,本地统计信息很快就会过时。
以下选项控制这种 ANALYZE 操作的行为:
analyze_sampling (string)
该选项可为外表或外部服务器指定,决定外表上的 ANALYZE 是在远端对数据采样,还是读取并传输所有数据然后在本地采样。支持的值为 off、random、system、bernoulli 与 auto。off 禁用远程采样,因此所有数据都被传输并在本地采样。random 使用 random() 函数选择返回的行来执行远程采样,而 system 与 bernoulli 依赖同名的内置 TABLESAMPLE 方法。random 可用于所有远程服务器版本,而 TABLESAMPLE 只从 9.5 起受支持。auto(默认值)自动选择推荐的采样方法;目前它意味着根据远程服务器版本选择 bernoulli 或 random。
默认情况下,只有使用内置操作符与函数的 WHERE 子句会被考虑在远程服务器上执行。涉及非内置函数的子句会在取回行后在本地检查。如果这类函数在远程服务器上可用,并且可以确信产生与本地相同的结果,那么把这类 WHERE 子句发送到远端执行可以改善性能。该行为可以用以下选项控制:
extensions (string)该选项是 PostgreSQL 扩展名称的逗号分隔列表,这些扩展以兼容的版本同时安装在本地与远程服务器上。不可变的且属于列表中扩展的函数与操作符将被视为可下推到远程服务器执行。该选项只能为外部服务器指定,不能按表指定。
使用 extensions 选项时,由用户负责确保所列扩展在本地与远程服务器上都存在且行为完全一致。否则远程查询可能失败或出现意外行为。
fetch_size (integer)
该选项指定 postgres_fdw 每次取操作应获取的行数。它可为外表或外部服务器指定。表上的选项覆盖服务器上的选项。默认值为 100。
batch_size (integer)
该选项指定 postgres_fdw 每次插入操作应插入的行数。它可为外表或外部服务器指定。表上的选项覆盖服务器上的选项。默认值为 1。
注意 postgres_fdw 一次实际插入的行数取决于列数与提供的 batch_size 值。批次作为单条查询执行,而 libpq 协议(postgres_fdw 用它连接远程服务器)把单条查询的参数数量限制为 65535。当列数 * batch_size 超过该限制时,batch_size 会被调整以避免错误。
该选项同样适用于向外表复制数据的情况。此时 postgres_fdw 一次实际复制的行数以与插入情况类似的方式确定,但由于 COPY 命令的实现限制,最多为 1000。
postgres_fdw 支持异步执行,它并发而非串行地运行 Append 节点的多个部分以提升性能。该执行可用以下选项控制:
async_capable (boolean)
该选项控制 postgres_fdw 是否允许外表为异步执行而被并发扫描。它可为外表或外部服务器指定。表级选项覆盖服务器级选项。默认值为 false。
为确保从外部服务器返回的数据一致,postgres_fdw 对给定的外部服务器只打开一个连接,并且即使涉及多个外表也会顺序执行针对该服务器的所有查询,除非这些表受不同用户映射的约束。在这种情况下,禁用该选项以消除与异步运行查询相关的开销可能带来更好的性能。
即使 Append 节点同时包含同步执行的子计划与异步执行的子计划,异步执行也会生效。在这种情况下,如果异步子计划是使用 postgres_fdw 处理的,那么在至少一个同步子计划返回所有元组之前,异步子计划的元组不会被返回,因为该同步子计划是在异步子计划等待发送到外部服务器的异步查询的结果期间执行的。这种行为可能在未来的版本中改变。
如事务管理一节所述,postgres_fdw 通过创建相应的远程事务来管理事务,并通过创建相应的远程子事务来管理子事务。当当前本地事务涉及多个远程事务时,默认情况下 postgres_fdw 在本地事务提交或中止时串行地提交或中止那些远程事务。当当前本地子事务涉及多个远程子事务时,默认情况下 postgres_fdw 在本地子事务提交或中止时串行地提交或中止那些远程子事务。可以用以下选项改善性能:
parallel_commit (boolean)
该选项控制 postgres_fdw 在本地事务提交时是否并行提交该本地事务中在外部服务器上打开的远程事务。该设置同样适用于远程与本地子事务。该选项只能为外部服务器指定,不能按表指定。默认值为 false。
parallel_abort (boolean)
该选项控制 postgres_fdw 在本地事务中止时是否并行中止该本地事务中在外部服务器上打开的远程事务。该设置同样适用于远程与本地子事务。该选项只能为外部服务器指定,不能按表指定。默认值为 false。
如果本地事务涉及多个启用了这些选项的外部服务器,那么当本地事务提交或中止时,这些外部服务器上的多个远程事务会跨这些外部服务器并行提交或中止。
启用这些选项后,当本地事务提交或中止时,拥有许多远程事务的外部服务器可能受到负面的性能影响。
默认情况下,所有使用 postgres_fdw 的外表都被假定为可更新的。这可以用以下选项覆盖:
updatable (boolean)
该选项控制 postgres_fdw 是否允许使用 INSERT、UPDATE 与 DELETE 命令修改外表。它可为外表或外部服务器指定。表级选项覆盖服务器级选项。默认值为 true。
当然,如果远程表实际上不可更新,无论如何都会发生错误。使用该选项主要允许在不查询远程服务器的情况下在本地抛出错误。不过请注意,information_schema 视图会根据该选项的设置报告 postgres_fdw 外表是否可更新,而不对远程服务器做任何检查。
默认情况下,所有使用 postgres_fdw 的外表都被假定为可截断的。这可以用以下选项覆盖:
truncatable (boolean)
该选项控制 postgres_fdw 是否允许使用 TRUNCATE 命令截断外表。它可为外表或外部服务器指定。表级选项覆盖服务器级选项。默认值为 true。
当然,如果远程表实际上不可截断,无论如何都会发生错误。使用该选项主要允许在不查询远程服务器的情况下在本地抛出错误。
postgres_fdw 能够使用 IMPORT FOREIGN SCHEMA 导入外部表定义。该命令在本地服务器上创建与远程服务器上存在的表或视图相匹配的外表定义。如果要导入的远程表具有用户定义数据类型的列,本地服务器必须有同名的兼容类型。
导入行为可以用以下选项定制(在 IMPORT FOREIGN SCHEMA 命令中给出):
import_collate (boolean)
该选项控制从外部服务器导入的外表定义中是否包含列的 COLLATE 选项。默认值为 true。如果远程服务器拥有的排序规则名称集合与本地服务器不同(在不同操作系统上运行时很可能如此),你可能需要关闭它。但如果这样做,被导入表列的排序规则与底层数据不匹配的风险非常严重,会导致异常的查询行为。
即使该参数设为 true,导入排序规则为远程服务器默认值的列也可能有风险。它们会以 COLLATE "default" 被导入,这会选择本地服务器的默认排序规则,而后者可能不同。
import_default (boolean)
该选项控制从外部服务器导入的外表定义中是否包含列的 DEFAULT 表达式。默认值为 false。如果启用该选项,要警惕那些在本地服务器上计算结果可能与远程服务器上不同的默认值;nextval() 是常见的问题来源。如果导入的默认表达式使用了本地不存在的函数或操作符,IMPORT 会整体失败。
import_generated (boolean)
该选项控制从外部服务器导入的外表定义中是否包含列的 GENERATED 表达式。默认值为 true。如果导入的生成表达式使用了本地不存在的函数或操作符,IMPORT 会整体失败。
import_not_null (boolean)
该选项控制从外部服务器导入的外表定义中是否包含列的 NOT NULL 约束。默认值为 true。
注意,NOT NULL 以外的约束永远不会从远程表导入。虽然 PostgreSQL 支持外表上的检查约束,但没有自动导入它们的机制,因为约束表达式在本地与远程服务器上求值结果不同的风险是存在的。检查约束行为的任何此类不一致都可能导致难以发现的查询优化错误。因此,如果你想导入检查约束,必须手动进行,并且应仔细验证每一个的语义。关于外表上检查约束处理的更多细节,请参见 CREATE FOREIGN TABLE。
作为其他表分区的表或外表只有在 LIMIT TO 子句中显式指定时才会被导入。否则它们会被自动排除在 IMPORT FOREIGN SCHEMA 之外。由于所有数据都可以通过作为分区层级根的分区表访问,只导入分区表就应该能访问所有数据而无需创建额外对象。
默认情况下,postgres_fdw 建立的到外部服务器的所有连接都会在本地会话中保持打开以便重用。
keep_connections (boolean) #
该选项控制 postgres_fdw 是否保持到外部服务器的连接打开,以便后续查询重用它们。它只能为外部服务器指定。默认值为 on。设为 off 时,到该外部服务器的所有连接会在每个事务结束时被丢弃。
use_scram_passthrough (boolean) #
该选项控制 postgres_fdw 是否使用 SCRAM 透传认证连接外部服务器。它可为外部服务器或用户映射指定。用户映射设置覆盖外部服务器设置。使用 SCRAM 透传认证时,postgres_fdw 使用 SCRAM 散列的秘密(而非明文用户密码)连接远程服务器。这避免了在 PostgreSQL 系统目录中存储明文用户密码。
使用 SCRAM 透传认证的要求:
远程服务器必须请求 scram-sha-256 认证方法;否则连接会失败。
远程服务器可以是任何支持 SCRAM 的 PostgreSQL 版本。use_scram_passthrough 的支持只要求在客户端(FDW)一侧。
用户映射密码不会被使用。
运行 postgres_fdw 的服务器与远程服务器必须为 postgres_fdw 用于在外部服务器上认证的用户拥有完全相同的 SCRAM 秘密(加密后的密码)(相同的盐与迭代次数,不只是相同的密码)。
由此推论,如果要对多个主机建立 FDW 连接,例如用于分区外表/分片,则所有主机都必须为相关用户拥有相同的 SCRAM 秘密。
发起外发 FDW 连接的 PostgreSQL 实例上的当前会话,其入站客户端连接也必须使用 SCRAM 认证。(因此称为“透传”:进出都必须使用 SCRAM。)这是 SCRAM 协议的技术要求。
postgres_fdw_get_connections(
IN check_conn boolean DEFAULT false, OUT server_name text,
OUT user_name text, OUT valid boolean, OUT used_in_xact boolean,
OUT closed boolean, OUT remote_backend_pid int4)
returns setof record该函数返回 postgres_fdw 从本地会话到外部服务器建立的所有打开连接的信息。如果没有打开的连接,则不返回记录。
如果 check_conn 设为 true,该函数会检查每个连接的状态,并把结果显示在 closed 列中。该功能目前只在支持对 poll 系统调用的非标准 POLLRDHUP 扩展的系统上可用,包括 Linux。它可用于检查事务中使用的所有连接是否仍然打开。如果任何连接被关闭,事务就无法成功提交,因此一旦检测到关闭的连接就尽快回滚比继续执行到底更好。如果该函数报告 used_in_xact 与 closed 均为 true 的连接,用户可以立即回滚事务。
该函数的用法示例:
postgres=# SELECT * FROM postgres_fdw_get_connections(true); server_name | user_name | valid | used_in_xact | closed | remote_backend_pid -------------+-----------+-------+--------------+----------------------------- loopback1 | postgres | t | t | f | 1353340 loopback2 | public | t | t | f | 1353120 loopback3 | | f | t | f | 1353156
输出列见 Table F.28。
Table F.28. postgres_fdw_get_connections 输出列
| 列 | 类型 | 描述 |
|---|---|---|
server_name | text |
该连接的外部服务器名称。如果服务器被删除但连接保持打开(即被标记为无效),该值为 NULL。
|
user_name | text |
映射到该连接外部服务器的本地用户的名称;如果使用公共映射则为 public。如果用户映射被删除但连接保持打开(即被标记为无效),该值为 NULL。
|
valid | boolean | 如果该连接无效则为假,意味着它被用在当前事务中,但其外部服务器或用户映射已被更改或删除。无效连接会在事务结束时关闭。否则返回真。 |
used_in_xact | boolean | 如果该连接被用在当前事务中则为真。 |
closed | boolean |
如果该连接已关闭则为真,否则为假。如果 check_conn 设为 false,或连接状态检查在该平台上不可用,则返回 NULL。
|
remote_backend_pid | int4 |
在外部服务器上处理该连接的远程后端的进程 ID。如果远程后端被终止且连接已关闭(closed 设为 true),这里仍会显示已终止后端的进程 ID。
|
postgres_fdw_disconnect(server_name text) returns boolean
该函数丢弃 postgres_fdw 从本地会话建立到给定名称外部服务器的打开连接。注意可能存在使用不同用户映射到给定服务器的多个连接。如果这些连接被用在当前本地事务中,它们不会被断开,并会报告警告消息。如果该函数至少断开了一个连接,返回 true,否则返回 false。如果找不到给定名称的外部服务器,会报告错误。该函数的用法示例:
postgres=# SELECT postgres_fdw_disconnect('loopback1');
postgres_fdw_disconnect
-------------------------
t
postgres_fdw_disconnect_all() returns boolean
该函数丢弃 postgres_fdw 从本地会话建立到外部服务器的所有打开连接。如果这些连接被用在当前本地事务中,它们不会被断开,并会报告警告消息。如果该函数至少断开了一个连接,返回 true,否则返回 false。该函数的用法示例:
postgres=# SELECT postgres_fdw_disconnect_all(); postgres_fdw_disconnect_all ----------------------------- t
postgres_fdw 在第一次使用与外部服务器关联的外表的查询期间建立到该外部服务器的连接。默认情况下该连接会被保留,并在同一会话的后续查询中重用。该行为可以用外部服务器的 keep_connections 选项控制。如果使用多个用户身份(用户映射)访问外部服务器,则会为每个用户映射建立一个连接。
更改外部服务器或用户映射的定义或删除它们时,相关联的连接会被关闭。但请注意,如果任何连接正被当前本地事务使用,它们会保留到事务结束。被关闭的连接会在未来使用外表的查询需要时重新建立。
一旦建立了到外部服务器的连接,默认情况下它会一直保留,直到本地或相应的远程会话退出。要显式断开连接,可以禁用外部服务器的 keep_connections 选项,或使用
postgres_fdw_disconnect 与
postgres_fdw_disconnect_all 函数。例如,这些函数可以用来关闭不再需要的连接,从而释放外部服务器上的连接。
在引用某个外部服务器上任何远程表的查询期间,如果尚未有对应于当前本地事务的远程事务,postgres_fdw 会在远程服务器上打开一个事务。当本地事务提交或中止时,远程事务也会提交或中止。保存点也以类似方式通过创建相应的远程保存点来管理。
当本地事务具有 SERIALIZABLE 隔离级别时,远程事务使用 SERIALIZABLE 隔离级别;否则使用 REPEATABLE READ 隔离级别。这一选择确保如果查询在远程服务器上执行多次表扫描,它将为所有扫描获得快照一致的结果。其后果是,单个事务内的连续查询会从远程服务器看到相同的数据,即使远程服务器上由于其他活动正在发生并发更新。如果本地事务使用 SERIALIZABLE 或 REPEATABLE READ 隔离级别,这种行为本来就在预期之内;但对 READ
COMMITTED 本地事务而言可能令人意外。未来的 PostgreSQL 版本可能会修改这些规则。
请注意,postgres_fdw 目前不支持为两阶段提交准备远程事务。
postgres_fdw 尝试优化远程查询以减少从外部服务器传输的数据量。这通过把查询的 WHERE 子句发送到远程服务器执行,以及不获取当前查询不需要的表列来实现。为降低查询错误执行的风险,除非 WHERE 子句只使用内置数据类型、操作符与函数,或属于外部服务器 extensions 选项中所列扩展的数据类型、操作符与函数,否则它们不会被发送到远程服务器。此类子句中的操作符与函数还必须是 IMMUTABLE 的。对于 UPDATE 或 DELETE 查询,如果不存在无法发送到远程服务器的查询 WHERE 子句、没有本地连接、目标表上没有行级本地 BEFORE 或 AFTER 触发器或存储生成列,也没有来自父视图的 CHECK OPTION 约束,postgres_fdw 会尝试通过把整个查询发送到远程服务器来优化查询执行。在 UPDATE 中,赋给目标列的表达式必须只使用内置数据类型、IMMUTABLE 操作符或 IMMUTABLE 函数,以降低查询错误执行的风险。
当 postgres_fdw 遇到同一外部服务器上外表之间的连接时,它会把整个连接发送到外部服务器,除非由于某种原因它认为逐个从每张表获取行会更高效,或者所涉及的表引用受不同用户映射的约束。发送 JOIN 子句时,它采取与上述 WHERE 子句相同的防范措施。
实际发送到远程服务器执行的查询可以用 EXPLAIN VERBOSE 检查。
在 postgres_fdw 打开的远程会话中,search_path 参数被设为仅 pg_catalog,因此只有内置对象无需模式限定即可见。这对 postgres_fdw 自己生成的查询来说不是问题,因为它总是提供这种限定。不过,这对通过远程表上的触发器或规则在远程服务器上执行的函数可能构成危险。例如,如果远程表实际上是一个视图,该视图中使用的任何函数都会以受限的搜索路径执行。建议对这类函数中的所有名称进行模式限定,或者为这类函数附加 SET search_path 选项(参见 CREATE FUNCTION)以建立其期望的搜索路径环境。
postgres_fdw 同样为各种参数建立远程会话设置:
TimeZone 设为 UTC
DateStyle 设为 ISO
IntervalStyle 设为 postgres
extra_float_digits 对 9.0 及更新的远程服务器设为 3,对更老的版本设为 2
这些设置比 search_path 更不容易出问题,但如有需要也可以用函数的 SET 选项处理。
不建议通过更改这些参数的会话级设置来覆盖这一行为;那样很可能导致 postgres_fdw 出现故障。
postgres_fdw 可以与早至 PostgreSQL 8.3 的远程服务器配合使用。只读能力可以追溯到 8.1。
不过有一个限制:postgres_fdw 通常假定不可变的内置函数与操作符出现在外表的 WHERE 子句中时,发送到远程服务器执行是安全的。因此,远程服务器版本发布之后新增的内置函数可能被发送给它执行,导致 “函数不存在” 或类似错误。这类失败可以通过改写查询来规避,例如通过把外表引用嵌入带 OFFSET 0(作为优化屏障)的子 SELECT 中,并把有问题的函数或操作符放在该子 SELECT 之外。
另一个限制是,在外表上执行带 ON CONFLICT DO NOTHING 子句的 INSERT 语句时,远程服务器必须运行 PostgreSQL 9.5 或更高版本,因为更早的版本不支持该特性。
postgres_fdw 可以在等待事件类型 Extension 下报告以下等待事件:
PostgresFdwCleanupResult等待远程服务器上的事务中止。
PostgresFdwConnect等待建立到远程服务器的连接。
PostgresFdwGetResult等待从远程服务器接收查询结果。
postgres_fdw.application_name (string)
#
指定 postgres_fdw 建立到外部服务器的连接时使用的 application_name 配置参数的值。它会覆盖服务器对象的 application_name 选项。请注意,更改该参数在现有连接重新建立之前不会影响它们。
postgres_fdw.application_name 可以是任意长度的任意字符串,甚至可以包含非 ASCII 字符。不过,当它被传递并用作外部服务器中的 application_name 时,请注意它会被截断到少于 NAMEDATALEN 个字符。可打印 ASCII 字符以外的任何字符都会被替换为 C 风格的十六进制转义。详情参见 application_name。
% 字符开始被替换为状态信息的 “转义序列”,如下所述。无法识别的转义会被忽略。其他字符会原样复制到应用程序名称。注意,不允许在 % 与选项之间指定加/减号或数字字面量来实现对齐与填充。
| 转义 | 效果 |
|---|---|
%a | 本地服务器上的应用程序名称 |
%c | 本地服务器上的会话 ID (详情参见 log_line_prefix) |
%C | 本地服务器上的集簇名称 (详情参见 cluster_name) |
%u | 本地服务器上的用户名 |
%d | 本地服务器上的数据库名 |
%p | 本地服务器上后端的进程 ID |
%% | 字面量 % |
例如,假设用户 local_user 从数据库 local_db 以用户 foreign_user 的身份建立到 foreign_db 的连接,设置 'db=%d, user=%u' 会被替换为 'db=local_db, user=local_user'。
下面是使用 postgres_fdw 创建外表的示例。首先安装扩展:
CREATE EXTENSION postgres_fdw;
然后使用 CREATE SERVER 创建外部服务器。在本例中,我们希望连接到主机 192.83.123.89 上监听端口 5432 的 PostgreSQL 服务器。连接所访问的数据库在远程服务器上名为 foreign_db:
CREATE SERVER foreign_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host '192.83.123.89', port '5432', dbname 'foreign_db');
还需要使用 CREATE USER MAPPING 定义一个用户映射,以标识将在远程服务器上使用的角色:
CREATE USER MAPPING FOR local_user
SERVER foreign_server
OPTIONS (user 'foreign_user', password 'password');
现在可以用 CREATE FOREIGN TABLE 创建外表了。在本例中,我们希望访问远程服务器上名为 some_schema.some_table 的表。它的本地名称将是 foreign_table:
CREATE FOREIGN TABLE foreign_table (
id integer NOT NULL,
data text
)
SERVER foreign_server
OPTIONS (schema_name 'some_schema', table_name 'some_table');
至关重要的是,在 CREATE FOREIGN TABLE 中声明的列的数据类型与其他属性必须与实际的远程表匹配。列名也必须匹配,除非你为个别列附加 column_name 选项来说明它们在远程表中的名称。在许多情况下,使用
IMPORT FOREIGN SCHEMA
比手工构建外表定义更可取。
Shigeru Hanada <shigeru.hanada@gmail.com>