PostgreSQL 14中的postgres_fdw增強功能


本文抄自:

https://mp.weixin.qq.com/s/7XjPa-ZeU8mNCvcIwOTHrA

 

Foreign Data Wrappers(FDW)提供了一種機制,通過這種機制,可以使用常規SQL查詢訪問PostgreSQL之外的數據。PostgreSQL附帶了“File FDW”和“PostgreSQL FDW”。PostgreSQL FDW可能看起來有悖常理,但它是一個非常有用的功能。這個版本的FDW有一些非常有用的更新。

所以,讓我們開始了解發生了什么變化。

性能特征

如果您已經在使用PostgreSQL FDW,請注意性能的改進

1 – 並行/異步 外部掃描

(允許一個查詢引用多個外部表,並行執行外部表掃描)

當在多台服務器上執行遠程聚合和遠程連接時,可能會造成性能噩夢。現在可以異步並行執行。之前的順序執行非常緩慢,在某些情況下,速度會很慢。為此,添加了一個新的選項async_capable,它允許並行計划和執行外部表掃描。

創建服務和用戶映射

-- Create foreign server 1.CREATE SERVER postgres_svr1FOREIGN DATA WRAPPER postgres_fdwOPTIONS (host '127.0.0.1', async_capable "true");
-- Create foreign server 2.CREATE SERVER postgres_svr2FOREIGN DATA WRAPPER postgres_fdwOPTIONS (host '127.0.0.1', async_capable "true");
CREATE USER MAPPING FOR vagrantSERVER postgres_svr1OPTIONS (user 'postgres', password 'pass');
CREATE USER MAPPING FOR vagrantSERVER postgres_svr2OPTIONS (user 'postgres', password 'pass');
創建本地表
CREATE TABLE parent_local (a INTEGER, b CHAR, c TEXT, d VARCHAR(255)) PARTITION BY RANGE (a);
CREATE TABLE child_local1 (a INTEGER, b CHAR, c TEXT, d VARCHAR(255));
CREATE TABLE child_local2 (a int, b CHAR, c text, d VARCHAR(255));
GRANT ALL ON child_local1 to postgres;
GRANT ALL ON child_local2 to postgres;

創建外部表

CREATE FOREIGN TABLE parent_remote1
PARTITION OF parent_local VALUES FROM 1000 TO 2000
SERVER postgres_svr1 OPTIONS table_name 'child_local1');

CREATE FOREIGN TABLE parent_remote2
PARTITION OF parent_local
FOR VALUES FROM 2000 TO 3000
SERVER postgres_svr2 OPTIONS table_name 'child_local2');

看看計划樹,現在你可以在計划樹中看到兩個異步的外部掃描計划。

CREATE TABLE sample_table (a INTEGER, b CHAR, c TEXT, d VARCHAR(255));

EXPLAIN (VERBOSE, COSTS OFF)
INSERT INTO sample_table SELECT * FROM parent_local WHERE a % 100 = 0;
                                          QUERY PLAN
----------------------------------------------------------------------------------------------
 Insert on public.sample_table
   ->  Append
         ->  Async Foreign Scan on public.parent_remote1 parent_local_1
               Output: parent_local_1.a, parent_local_1.b, parent_local_1.c, parent_local_1.d
               Remote SQL: SELECT a, b, c, d FROM public.child_local1 WHERE (((a % 100) = 0))
         ->  Async Foreign Scan on public.parent_remote2 parent_local_2
               Output: parent_local_2.a, parent_local_2.b, parent_local_2.c, parent_local_2.d
               Remote SQL: SELECT a, b, c, d FROM public.child_local2 WHERE (((a % 100) = 0))
(8 rows)

2 – 批量插入

(允許postgres_fdw批量插入行。)

現在,批量插入功能已添加到FDW中,postgres_fdw現在支持該功能。其他FDW也有機會實現批量插入。你可以在這里看到。

功能特性

1 – TRUNCATE 命令

(允許TRUNCATE對外部表進行操作)

這意味着它會向外部服務器出TRUNCATE命令,並在表上執行。這個功能是在postgres_fdw中實現的。下面是一個例子。

CREATE SERVER postgres_svr 
       FOREIGN DATA WRAPPER postgres_fdw 
       OPTIONS (host '127.0.0.1');

CREATE USER MAPPING FOR vagrant
       SERVER postgres_svr
       OPTIONS (user 'postgres', password 'pass');

CREATE FOREIGN TABLE foo_remote (a INTEGER,
                                 b CHAR,
                                 c TEXT,
                                 d VARCHAR(255))
       SERVER postgres_svr
       OPTIONS(table_name 'foo_local');

現在,可以TRUNCATE外部表。

postgres=# TRUNCATE foo_remote;
TRUNCATE TABLE

2 – LIMIT TO 子分區

(如果指定IMPORT FOREIGN SCHEMA … LIMIT TO,則允許postgres_fdw導入表分區。)

postgres_fdw不允許導入表分區,因為可以使用根分區訪問數據。但是,如果用戶想要導入分區表分區,PostgreSQL 14添加了一個新的選項LIMIT TO

在遠程計算機上創建一個新schema,並添加一個父表foo_schema.foo_table_parent和一個子表foo_schema.foo_table_child

postgres=# \d+ foo_schema.*
                                   Table "foo_schema.foo_table_child"
 Column |  Type   | Collation | Nullable | Default | Storage | Compression | Stats target | Description 
--------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
 a      | integer |           |          |         | plain   |             |              | 
Partition of: foo_schema.foo_table_parent FOR VALUES FROM (0) TO (10)

Partition constraint: ((a IS NOT NULL) AND (a >= 0) AND (a < 10))
Access method: heap

                            Partitioned table "foo_schema.foo_table_parent"
 Column |  Type   | Collation | Nullable | Default | Storage | Compression | Stats target | Description 
--------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
 a      | integer |           |          |         | plain   |             |              | 
Partition key: RANGE (a)
Partitions: foo_schema.foo_table_child FOR VALUES FROM (0) TO (10)

在不指定LIMIT TO的情況下導入schema,只能看到導入的父表。

IMPORT FOREIGN SCHEMA foo_schema FROM SERVER postgres_svr INTO bar_schema;
postgres=# \d+ bar_schema.*
                                 Foreign table "bar_schema.foo_table_parent"
 Column |  Type   | Collation | Nullable | Default |    FDW options    | Storage | Stats target | Description 
--------+---------+-----------+----------+---------+-------------------+---------+--------------+-------------
 a      | integer |           |          |         | (column_name 'a') | plain   |              | 
Server: postgres_svr
FDW options: (schema_name 'foo_schema', table_name 'foo_table_parent')

如果您在LIMIT TO子句中顯式指定了分區表,那么它將導入該表。

postgres=# IMPORT FOREIGN SCHEMA foo_schema LIMIT TO (foo_table_parent, foo_table_child)
            FROM SERVER loopback INTO bar_schema;
IMPORT FOREIGN SCHEMA

postgres=# \d+ bar_schema.*
                                  Foreign table "bar_schema.foo_table_child"
 Column |  Type   | Collation | Nullable | Default |    FDW options    | Storage | Stats target | Description 
--------+---------+-----------+----------+---------+-------------------+---------+--------------+-------------
 a      | integer |           |          |         | (column_name 'a') | plain   |              | 
Server: loopback
FDW options: (schema_name 'foo_schema', table_name 'foo_table_child')

                                 Foreign table "bar_schema.foo_table_parent"

 Column |  Type   | Collation | Nullable | Default |    FDW options    | Storage | Stats target | Description 
--------+---------+-----------+----------+---------+-------------------+---------+--------------+-------------
 a      | integer |           |          |         | (column_name 'a') | plain   |              | 
Server: loopback
FDW options: (schema_name 'foo_schema', table_name 'foo_table_parent')

3 – 活動和有效的連接列表

(添加postgres_fdw_get_connections函數以報告打開的外部服務連接)

添加了一個新函數postgres_fdw_get_connections()。該函數將打開的連接名本地會話返回到postgres_fdw的外部服務。它還輸出連接的有效性。

postgres=# SELECT * FROM postgres_fdw_get_connections() ORDER BY 1;
    server_name    | valid 
-------------------+-------
 postgres_svr      | t
 postgres_svr_bulk | t
(2 rows)

現在斷開所有連接並重試查詢。

postgres=# SELECT 1 FROM postgres_fdw_disconnect_all();
 ?column? 
----------
        1
(1 row)

postgres=# SELECT * FROM postgres_fdw_get_connections() ORDER BY 1;
 server_name | valid 
-------------+-------
(0 rows)

4 – 保持連接

(添加丟棄緩存的連接功能)

添加了一個新選項keep_connections,以保持連接處於活動狀態,以便后續查詢可以重用它們。默認情況下,此選項處於on狀態,但如果off,則在事務結束時將丟棄連接。

關閉這個選項

ALTER SERVER loopback OPTIONS (keep_connections 'off');

使用遠程查詢建立連接。

postgres=# BEGIN;
BEGIN

postgres=*# select * from foo_remote;
 a | b | c | d 
---+---+---+---
(0 rows)

postgres=*# END;
COMMIT

postgres=# SELECT * FROM postgres_fdw_get_connections() ORDER BY 1;
 server_name | valid 
-------------+-------
(0 rows)

設置 keep_connections 選項為 on

ALTER SERVER postgres_svr options (set keep_connections 'on');
postgres=# BEGIN;
BEGIN
postgres=*# select * from foo_remote;
 a | b | c | d 
---+---+---+---
(0 rows)

-- Establish the connection using the remote query.

postgres=*# END;
COMMIT

postgres=# SELECT * FROM postgres_fdw_get_connections() ORDER BY 1;
 server_name  | valid 
--------------+-------
 postgres_svr | t
(1 row)

5 – 重建斷開連接

(必要時允許postgres_fdw重新建立外部服務連接)

以前,當遠程服務重新啟動並且postgres_fdw連接斷開時,由於緩存的連接不再可用,因此引發了錯誤。這在PostgreSQL中是固定的,在任何情況下,連接都會斷開並且不再存在於緩存中,postgres_fdw將重新建立連接。

 

結論

FDW API很有希望在每個版本中都得到擴展,但PostgreSQL 14提供了一些以用戶為中心的新功能。與性能相關的改進為許多相關用例使用FDW提供了另一個理由。該功能肯定會在接下來的幾個版本中添加,使這些版本更具性能,更易於使用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM