PostgreSQL fdw 상세 설명

32982 단어 PostgreSQL
postgres fdw 는 외부 접근 인터페이스 로 외부 에 저 장 된 데 이 터 를 방문 할 수 있 습 니 다.이 데 이 터 는 외부 pg 데이터 베이스 일 수도 있 고 Oacle,my sql 등 데이터 베 이 스 를 방문 할 수도 있 으 며 심지어 파일 일 수도 있 습 니 다.
현재 지원 하 는 fdw 외부 데이터 원본:https://wiki.postgresql.org/wiki/Foreign_data_wrappers
FDW 는 보통 어떤 장면 에 쓰 입 니까?예 를 들 어 sharding,예 를 들 어 pgsharedman 플러그 인 은 postgres 를 사용 합 니 다.fdw 와 pgpathman 의 플러그 인 은 데이터 의 블록 을 실현 합 니 다.동기 데이터,etl,데이터 이전 등.
postgres_fdw 사용 예:여기 2 개의 데이터베이스 db 01,db 02,2 개의 사용자 user 01,user 02 를 각각 로 컬 과 원 격 데이터베이스 와 사용자 로 만 듭 니 다.
bill=# create user user01 superuser  password 'bill';    
CREATE ROLE
bill=# create database db01 owner=user01 TEMPLATE=template0 LC_CTYPE='zh_CN.UTF-8';
CREATE DATABASE
bill=# create user user02 superuser password 'bill';
CREATE ROLE
bill=# create database db02 with owner=user02 TEMPLATE=template0 LC_CTYPE='zh_CN.UTF-8';
CREATE DATABASE

다음 원 격 db 02 아래 에 표를 만 듭 니 다:
bill=# \c db02 user02 
You are now connected to database "db02" as user "user02".
db02=# create table table1 (id int, crt_Time timestamp, info text, c1 int);
CREATE TABLE
db02=#  create table table2 (id int, crt_Time timestamp, info text, c1 int); 
CREATE TABLE
db02=# insert into table1 select generate_series(1,1000000), clock_timestamp(), md5(random()::text), random()*1000;  
INSERT 0 1000000
db02=# insert into table2 select generate_series(1,1000000), clock_timestamp(), md5(random()::text), random()*1000;  
INSERT 0 1000000

fdw 접근 데 이 터 를 사용 하려 면 먼저 확보 해 야 합 니 다:네트워크 통,데이터베이스 방화벽(pghba,conf)정상 적 이 고 원 격 데이터 베 이 스 를 사용 하 는 사용 자 는 표 와 관련 된 권한 이 있어 야 합 니 다.
그리고 로 컬 db 01 에 server 를 만 듭 니 다:
db01=# CREATE SERVER db02  
db01-#         FOREIGN DATA WRAPPER postgres_fdw  
db01-#         OPTIONS (host '192.168.7.xxx', port '1921', dbname 'db02'); 
CREATE SERVER
db01=# select * from pg_foreign_server ;  
  oid  | srvname | srvowner | srvfdw | srvtype | srvversion | srvacl |                 srvoptions                 
-------+---------+----------+--------+---------+------------+--------+--------------------------------------------
 50361 | db02    |    50345 |  50350 |         |            |        | {host=192.168.7.xxx,port=1921,dbname=db02}
(1 row)

사용자 매 핑 설정:
db01=# CREATE USER MAPPING FOR user01  
db01-# SERVER db02  
db01-# OPTIONS (user 'user02', password 'bill'); 
CREATE USER MAPPING

그 다음 에 forein table 을 만 들 수 있 습 니 다.-방법 1:일괄 가 져 오기,이런 흔 한 것 은 한 번 에 한 모드 의 모든 표를 가 져 올 수 있 습 니 다.
db01=# import foreign schema public from server db02 into sch1;
IMPORT FOREIGN SCHEMA
db01=# \det sch1.*
  List of foreign tables
 Schema | Table  | Server 
--------+--------+--------
 sch1   | table1 | db02
 sch1   | table2 | db02
(2 rows)

–방법 2:단일 생 성
db01=#  CREATE FOREIGN TABLE sch1.table1 (  
db01(#    id int, crt_Time timestamp, info text, c1 int)   
db01-#          SERVER db02  
db01-#          OPTIONS (schema_name 'public', table_name 'table1');  
CREATE FOREIGN TABLE

조회:
db01=#  select count(*) from sch1.table1; 
  count  
---------
 1000000
(1 row)

db01=#  select count(*) from sch1.table2;
  count  
---------
 1000000
(1 row)

sql 이 원 격 에서 어떻게 실행 되 는 지 explain verbose 에서 볼 수 있 습 니 다.
db01=# explain verbose  select count(*) from sch1.table1; 
                     QUERY PLAN                     
----------------------------------------------------
 Foreign Scan  (cost=108.53..152.69 rows=1 width=8)
   Output: (count(*))
   Relations: Aggregate on (sch1.table1)
   Remote SQL: SELECT count(*) FROM public.table1
(4 rows)

pushdown:우리 가 로 컬 에서 실행 하 는 문 구 는 모든 pushdown 이 원 격 으로 실행 되 는 것 이 아 닙 니 다.현 재 는 데이터 형식,immutable 연산 자,immutable 함수 만 지원 합 니 다.이것 도 이해 하기 쉽 습 니 다.pg 는 사용자 가 데이터 형식,연산 자 등 을 스스로 정의 할 수 있 기 때 문 입 니 다.만약 에 우리 가 현지에서 새로운 연산 자 를 정 의 했 지만 원 격 에 있 지 않 으 면 원 격 으로 push 할 수 없습니다.또한 로 컬 과 원 격 에서 같은 extension 을 만 들 었 다 면 이 extension 이 자체 적 으로 가지 고 있 는 연산 자 와 함 수 는 pushdown 할 수 있 습 니 다.
–projection
db01=# explain verbose select id from sch1.table2;   
                              QUERY PLAN                              
----------------------------------------------------------------------
 Foreign Scan on sch1.table2  (cost=100.00..197.75 rows=2925 width=4)
   Output: id
   Remote SQL: SELECT id FROM public.table2
(3 rows)

–where
db01=# explain verbose select * from sch1.table1 where id=1;  
                                   QUERY PLAN                                    
---------------------------------------------------------------------------------
 Foreign Scan on sch1.table1  (cost=100.00..124.33 rows=6 width=48)
   Output: id, crt_time, info, c1
   Remote SQL: SELECT id, crt_time, info, c1 FROM public.table1 WHERE ((id = 1))
(3 rows)

–agg
db01=# explain verbose select count(*) from sch1.table1;   
                     QUERY PLAN                     
----------------------------------------------------
 Foreign Scan  (cost=108.53..152.69 rows=1 width=8)
   Output: (count(*))
   Relations: Aggregate on (sch1.table1)
   Remote SQL: SELECT count(*) FROM public.table1
(4 rows)

–join
db01=# explain verbose select t1.* from sch1.table1 t1 inner join sch1.table2 using (id) limit 2;  
                                                                     QUERY PLAN                                                                     
----------------------------------------------------------------------------------------------------------------------------------------------------
 Foreign Scan  (cost=100.00..100.99 rows=2 width=48)
   Output: t1.id, t1.crt_time, t1.info, t1.c1
   Relations: (sch1.table1 t1) INNER JOIN (sch1.table2)
   Remote SQL: SELECT r1.id, r1.crt_time, r1.info, r1.c1 FROM (public.table1 r1 INNER JOIN public.table2 r2 ON (((r1.id = r2.id)))) LIMIT 2::bigint
(4 rows)

–limit pg 12 이전 limit 작업 은 원 격 에서 실행 되 지 않 습 니 다.
db01=# explain verbose select * from sch1.table2 limit 10;   
                                   QUERY PLAN                                    
---------------------------------------------------------------------------------
 Foreign Scan on sch1.table2  (cost=100.00..100.37 rows=10 width=48)
   Output: id, crt_time, info, c1
   Remote SQL: SELECT id, crt_time, info, c1 FROM public.table2 LIMIT 10::bigint
(3 rows)

–sort
db01=# explain verbose select * from sch1.table2 order by id desc limit 10;    
                                                  QUERY PLAN                                                  
--------------------------------------------------------------------------------------------------------------
 Foreign Scan on sch1.table2  (cost=100.00..100.40 rows=10 width=48)
   Output: id, crt_time, info, c1
   Remote SQL: SELECT id, crt_time, info, c1 FROM public.table2 ORDER BY id DESC NULLS FIRST LIMIT 10::bigint
(3 rows)

제어 매개 변수:예 를 들 어 앞에서 언급 한 것 은 로 컬 과 원 격 에서 같은 extension 을 만 들 수 있 습 니 다.그러면 이 extension 이 자체 적 으로 가지 고 있 는 연산 자 와 함 수 는 pushdown 이 될 수 있 습 니 다.우 리 는 제어 매개 변수 extensions 를 통 해 설명 해 야 합 니 다.
db01=#  alter server db02 options (add extensions 'dblink');
ALTER SERVER
db01=#  alter server db02 options (set extensions 'dblink');   
ALTER SERVER
db01=# alter server db02 options (drop extensions ); 
ALTER SERVER

pull 은 원 격 데이터 pull 을 로 컬 로 가 져 와 조작 해 야 할 때 가 있 습 니 다.
db01=# create table t as select * from sch1.table1;   
SELECT 1000000
db01=#  explain verbose select count(*) from t join sch1.table1 t1 on (t.id=t1.id and t1.c1=1); 
                                       QUERY PLAN                                        
-----------------------------------------------------------------------------------------
 Aggregate  (cost=28038.83..28038.83 rows=1 width=8)
   Output: count(*)
   ->  Hash Join  (cost=147.05..27831.98 rows=82738 width=0)
         Hash Cond: (t.id = t1.id)
         ->  Seq Scan on public.t  (cost=0.00..21341.70 rows=1103170 width=4)
               Output: t.id, t.crt_time, t.info, t.c1
         ->  Hash  (cost=146.86..146.86 rows=15 width=4)
               Output: t1.id
               ->  Foreign Scan on sch1.table1 t1  (cost=100.00..146.86 rows=15 width=4)
                     Output: t1.id
                     Remote SQL: SELECT id FROM public.table1 WHERE ((c1 = 1))
(11 rows)

DML
db01=# explain verbose update sch1.table1 set crt_time=now() where id=1;  
                                          QUERY PLAN                                          
----------------------------------------------------------------------------------------------
 Update on sch1.table1  (cost=100.00..124.78 rows=6 width=54)
   Remote SQL: UPDATE public.table1 SET crt_time = $2 WHERE ctid = $1
   ->  Foreign Scan on sch1.table1  (cost=100.00..124.78 rows=6 width=54)
         Output: id, now(), info, c1, ctid
         Remote SQL: SELECT id, info, c1, ctid FROM public.table1 WHERE ((id = 1)) FOR UPDATE
(5 rows)

연결 탱크 는 pg 가 다 중 프로 세 스 의 구조 이기 때문에 모든 연결 에 대해 새로운 프로 세 스 를 fork 해 야 합 니 다.그러면 fdw 를 통 해 원 격 데 이 터 를 방문 하면 여러 프로 세 스 를 만 들 수 있 습 니까?postgres 사용fdw 는 하나의 session 에서 같은 foreign server 를 사용 하면 같은 프로 세 스 를 다시 사용 할 수 있 습 니 다.
병렬 postgresfdw 는 병행 작업 을 허용 합 니 다.예 를 들 어 큰 시 계 를 조작 하 는 것 은 병행 할 수 있 습 니 다.https://www.postgresql.org/docs/12/fdwhandler.html
사무 용 fdw 접근 데 이 터 는 어떻게 데이터 의 일치 성 을 보증 합 니까?이러한 측면 에서 2 단계 제출 방식 을 사용 하지 않 고 규정 한다.1.로 컬 업무 의 격 리 등급 이 SERIALIZABLE 이면 원 격 업무 의 격 리 등급 도 SERIALIZABLE 이다.2.로 컬 트 랜 잭 션 의 격 리 등급 이 다른 것 이 라면 원 격 트 랜 잭 션 의 격 리 등급 은 모두 REPEATABLE READ 입 니 다.

좋은 웹페이지 즐겨찾기