postgres_fdw访问存储在外部 PostgreSQL 服务器中的数据
文章目录
- 一、postgres_fdw 介绍
- 二、安装使用示例
- 三、成本估算
- 四、 远程执行选项
- 执行计划无法递推解决
- 参考文件:
一、postgres_fdw 介绍
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 创建外键表的示例。首先安装扩展:
CREATE EXTENSION postgres_fdw;
因为没有远端环境,接下来我将使用本地的其他数据库作为外部数据库。
后使用 CREATE SERVER 创建一个外部服务器。在此示例中,我们希望连接到侦听端口 5432 的主机 192.83.123.89 上的 PostgreSQL 服务器。在远程服务器上,连接到的数据库名为 foreign_db:
CREATE SERVER foreign_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host '****', port '5432', dbname 'foreign_db');
foreign_server是服务名,host是远端ip,port是远端端口,dbname是远端数据库名
还需要使用 CREATE USER MAPPING 定义用户映射,以识别将在远程服务器上使用的角色:
CREATE USER MAPPING FOR local_user
SERVER foreign_server
OPTIONS (user 'foreign_user', password 'password');
local_user是你本地的数据库用户名,foreign_server是上一步定的服务名,foreign_user是远端用户名,password是远端密码
现在可以使用 CREATE FOREIGN TABLE 创建外键表。在此示例中,我们希望访问远程服务器上名为 some_schema.some_table 的表。它的本地名称将是 foreign_table:
CREATE FOREIGN TABLE fdw_test1 (
id int
)
SERVER foreign_server
OPTIONS (schema_name 'public', table_name 'fdw_test1');
测试成功,能够成功的在postgres数据库中查到test数据库中的数据。
三、成本估算
postgres_fdw 通过对远程服务器执行查询来检索远程数据,因此理想情况下,扫描外部表的估计成本应该是远程服务器上完成此操作所需的成本,加上一些通信开销。获取此类估算的最可靠方法是询问远程服务器,然后添加一些开销 — 但对于简单的查询,可能不值得为获取成本估算而付出额外的远程查询成本。因此 postgres_fdw 提供以下选项来控制如何执行成本估算
use_remote_estimate (boolean)
此选项可以为外部表或外部服务器指定,它控制 postgres_fdw 是否发出远程 EXPLAIN 命令来获取成本估算。外部表的设置将覆盖其服务器的任何设置,但仅针对该表。默认值为 false。
fdw_startup_cost (floating point)
此选项可以为外部服务器指定,它是一个浮点值,将被添加到该服务器上任何外部表扫描的估计启动成本中。这表示建立连接、解析和规划远程端的查询等的额外开销。默认值为 100。
fdw_tuple_cost (floating point)
此选项可以为外部服务器指定,它是一个浮点值,用作该服务器上外部表扫描的每个元组的额外成本。这表示服务器之间的数据传输的额外开销。您可以增加或减少此数字,以反映到远程服务器的网络延迟较高或较低。默认值为 0.01。
当 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 (text)
此选项可以为外部表或外部服务器指定,它确定外部表上的 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。
执行计划无法递推解决
了解了以上内容,我们可以知道当查询设计到不稳定函数或者特定插件的函数时,执行计划将无法递推,所以我们需要解决这个问题就需要在连接中哦配置特定的插件。
比如以上这种情况:
alter server youerserver options(extensions 'postgis');
我们需要添加外部插件到服务中,就能解决问题。
参考文件:
pg官方文档