PostgreSQL-11.3-postgres-FDW-配置和體驗

1 摘要

本文首先總結了工做中配置postgres-fdw的關鍵步驟,而後針對外表查詢的幾個典型場景,記錄了每一種場景下,主節點是如何下推查詢到外節點的。node

2 環境配置

  • 配置兩臺數據庫服務器:node1:5432, node2:6432
  • 使用默認數據庫: postgres
node1                                  node2 
  |--------------------|                 |-------------------|
  |        user=user1 --------------------> user=user2       |
  | local table:   t0  |                 |                   |
  | foreign table: t1 --------------------> local table: t1  |
  |                    |                 |                   |
  | foreign table: t2 --------------------> local table: t2  | 
  |--------------------|                 |-------------------|

2.1 配置node2:

  • node2上建立數據庫帳號'user2'
  • node2上創建兩個表: t1, t2

2.1.1 使用超級用戶登陸node2,在node2上建立數據庫帳號'user2'

psql -h node2 -p 6432 -d postgres
CREATE ROLE user2 WITH LOGIN PASSWORD 'pwd#@1';
GRANT ALL PRIVILEGES ON DATABASE postgres to user2;

2.1.2 更改node2:pg_hba.conf,容許node1使用帳號user2訪問node2

  • node1的IP地址:192.168.199.110
host    postgres        user2           192.168.199.110/32      md5

2.1.3 在node2上,以user2身份,建立表: t1, t2

psql -h node2 -p 6432 -d postgres -U user2
create table t1 ( id int, name varchar(100));

create table t2 ( id int, name varchar(100));

2.2 配置node1

  • node1: 建立數據庫帳號'user1'
  • node1: 創建一個本地表t0,兩個外表: t1, t2,分別指向node2上的t1, t2

2.2.1 使用超級用戶,在node1上啓用postgres-fdw, 建立數據庫帳號'user1'

psql -h node1 -p 5432 -d postgres
create extension postgres_fdw;

CREATE ROLE user1 WITH LOGIN PASSWORD '#@1qw';
GRANT ALL PRIVILEGES ON DATABASE postgres to user1;
grant usage on foreign data wrapper postgres_fdw to user1;

2.2.2 node1上,以user1登陸

psql -h node1 -p 5432 -d postgres -U user1

2.2.3 node1上,使用user1帳號,建立本地表: t0

create table t0 ( id int, name varchar(100));

2.2.4 node1上,使用user1帳號,建立外表:t1, t2

;;外表t1,t2
node1.t1 ---> node2.t1
node1.t2 ---> node2.t2
create server fnode2
         foreign data wrapper postgres_fdw
         options (host 'node2', port '6432', dbname 'postgres');
 
create user mapping for user1
         server fnode2
         options (user 'user2', password 'pwd#@1'); 

create foreign table t1 (
         id int,
         name varchar(100)
)
server fnode2
options (schema_name 'public', table_name 't1');


create foreign table t2 (
         id int,
         name varchar(100)
)
server fnode2
options (schema_name 'public', table_name 't2');

2.3 加載數據,

  • 經過節點node1,分別向node1的三個表(node1.t0, node1.t1,node1.t2)插入數據
  • 三個表的數據相同,每一個表有100條數據
insert into t0 select generate_series(1,100), 'tom-'||generate_series(1,100) ;
insert into t1 select generate_series(1,100), 'tom-'||generate_series(1,100) ;
insert into t2 select generate_series(1,100), 'tom-'||generate_series(1,100) ;

三個表的數據相同:sql

id            name
----------------------
1             tom-1
2             tom-2
3             tom-3
...            ...

3. 探索外表查詢

3.1 node1單外表掃描

  • node1.t1是外表
  • 經過node1,查詢t1
  • node1把查詢,連帶查詢條件,推送到node2

node1上執行查詢:數據庫

psql -h node1 -U user1 -d postgres -c "select * from t1 where id=1;"

node2的執行過程以下:bash

START TRANSACTION ISOLATION LEVEL REPEATABLE READ;
DECLARE c1 CURSOR FOR SELECT id, name FROM public.t1 WHERE ((id = 1));
FETCH 100 FROM c1;
CLOSE c1;
COMMIT TRANSACTION;

3.2 node1上:單外表+單本地表join,推送到外表時無過濾條件(where)

  • t0是本地表
  • t1是外表

在node1上執行查詢服務器

psql -h node1 -U user1 -d postgres -c "select * from t0,t1 where t0.id=1 and t0.name=t1.name;"

下推到node2的查詢以下:app

START TRANSACTION ISOLATION LEVEL REPEATABLE READ;
DECLARE c1 CURSOR FOR SELECT id, name FROM public.t1;
FETCH 100 FROM c1;
FETCH 100 FROM c1;
CLOSE c1;
COMMIT TRANSACTION;

3.3 node1上:單外表+單本地表join,推送到外表時帶有過濾條件(where)

  • t0是本地表
  • t1是外表

在node1上執行查詢:post

psql -h node1 -U user1 -d postgres -c "select * from t0,t1 where t1.id=1 and t0.name=t1.name;"

下推到node2的查詢以下:code

START TRANSACTION ISOLATION LEVEL REPEATABLE READ;

DECLARE c1 CURSOR FOR
	SELECT id, name FROM public.t1 WHERE ((id = 1));

FETCH 100 FROM c1;
CLOSE c1;
COMMIT TRANSACTION;

3.4 node1上,雙外表join

  • t1是外表
  • t2是外表

經過node1執行:server

psql -h node1 -U user1 -d postgres -c "select * from t1,t2 where t1.id=1 and t1.name=t2.name;"

下推到node2的查詢以下:md5

START TRANSACTION ISOLATION LEVEL REPEATABLE READ;

DECLARE c1 CURSOR FOR
	SELECT r1.id, r1.name, r2.id, r2.name FROM (public.t1 r1 INNER JOIN public.t2 r2 ON (((r1.name = r2.name)) AND ((r1.id = 1))));

FETCH 100 FROM c1;
CLOSE c1;
COMMIT TRANSACTION;

3.5 node1上,對外表avg()

  • t1是外表

經過node1執行:

psql -h node1 -U user1 -d postgres -c "select avg(id) from t1 where id<100;"

下推到node2的查詢以下:

START TRANSACTION ISOLATION LEVEL REPEATABLE READ;
DECLARE c1 CURSOR FOR
	SELECT avg(id) FROM public.t1 WHERE ((id < 100));

FETCH 100 FROM c1;
CLOSE c1;
COMMIT TRANSACTION;

3.6 node1上,對外表sort

  • t1是外表

經過node1執行:

psql -h node1 -U user1 -d postgres -c "select * from t1 where id<100 order by name;"

下推到node2的查詢以下:

START TRANSACTION ISOLATION LEVEL REPEATABLE READ;

DECLARE c1 CURSOR FOR
	SELECT id, name FROM public.t1 WHERE ((id < 100)) ORDER BY name ASC NULLS LAST;

FETCH 100 FROM c1;
CLOSE c1;
COMMIT TRANSACTION;
相關文章
相關標籤/搜索