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
语句触发的行移动,但目前不处理将移动的行插入到的远程分区也是同一命令中其他位置更新的目标分区的情况。
通常建议将外部表的列声明为与远程表中的相应列具有完全相同的数据类型,如果适用,还需要声明相同排序规则。虽然 postgres_fdw
目前在必要时执行数据类型转换时相当宽容,但当类型或排序规则不匹配时,由于远程服务器对查询条件的解释可能与本地服务器不同,可能会出现令人惊讶的语义异常。
请注意,外部表声明的列数可以少于其底层远程表,或者列顺序可以不同。列与远程表的匹配是按名称进行的,而不是按位置。
使用 postgres_fdw
外部数据包装器的外部服务器可以具有 libpq 在连接字符串中接受的相同选项,如 第 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
等。他们还可以使用 peer
或 ident
认证模式授予的任何信任关系。(有关查找主目录的详细信息,请参见 第 32.16 节。)
这些选项可用于控制发送到远程 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
为 true 时,postgres_fdw
从远程服务器获取行数和成本估算,然后将 fdw_startup_cost
和 fdw_tuple_cost
加到成本估算中。当 use_remote_estimate
为 false 时,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
。
当然,如果远程表实际上不可更新,仍然会发生错误。此选项的使用主要允许在不查询远程服务器的情况下本地抛出错误。但请注意,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 版本。仅需要在客户端(FDW 端)支持 use_scram_passthrough
。
不使用用户映射密码。
运行 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
输出列在 表 F.28 中描述。
表 F.28. postgres_fdw_get_connections
输出列
列 | 类型 | 描述 |
---|---|---|
server_name |
text |
此连接的外部服务器名称。如果服务器已被删除但连接保持打开状态(即,标记为无效),则此项将为 NULL 。 |
user_name |
text |
映射到此连接的外部服务器的本地用户名称,如果使用公共映射,则为 public 。如果用户映射已被删除但连接保持打开状态(即,标记为无效),则此项将为 NULL 。 |
valid |
boolean |
如果此连接无效,则为 False,表示它在当前事务中使用,但其外部服务器或用户映射已被更改或删除。无效的连接将在事务结束时关闭。否则返回 True。 |
used_in_xact |
boolean |
如果此连接在当前事务中使用,则为 True。 |
closed |
boolean |
如果此连接已关闭,则为 True,否则为 False。NULL 在 check_conn 设置为 false 或此平台不支持连接状态检查时返回。 |
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
,因此只有内置对象在没有模式限定的情况下可见。这对于通过远程表上的触发器或规则在远程服务器上执行的函数来说不是问题。例如,如果远程表实际上是一个视图,那么在该视图中使用的任何函数都将在受限制的搜索路径下执行。建议对这些函数中的所有名称进行模式限定,或者将 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_db
,用户为 foreign_user
,设置 '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>
如果您在文档中发现任何不正确的内容、与您对特定功能的体验不符的内容或需要进一步澄清的内容,请使用 此表单 报告文档问题。