SlideShare a Scribd company logo
Federated
PostgreSQL
Who Am I?
●

Jim Mlodgenski
–
–

●

jimm@openscg.com
@jim_mlodgenski

Co-organizer of
–
–

●

NYC PUG (www.nycpug.org)
Philly PUG (www.phlpug.org)

CTO, OpenSCG
–

www.openscg.com
http://nyc.pgconf.us
What is a federated database?
“A federated database system is a type of meta-database
management system (DBMS), which transparently maps
multiple autonomous database systems into a single federated
database. The constituent databases are interconnected via a
computer network and may be geographically decentralized. ...
There is no actual data integration in the constituent disparate
databases as a result of data federation.”
-Wikipedia
How does PostgreSQL do it?
●

Uses Foreign Table Wrappers (FDW)

●

Used with SQL/MED
–
–

Management of External Data

–
●

New ANIS SQL 2003 Extension
Standard way of handling remote objects in SQL databases

Wrappers used by SQL/MED to access remotes data
sources
Types of Foreign Data Wrappers
●

SQL

●

NoSQL

●

File

●

Miscellaneous

●

PostgreSQL
SQL Wrappers
●

Oracle

●

SQLite

●

MySQL

●

JDBC

●

Informix

●

ODBC

●

Firebird
SQL Wrappers
CREATE SERVER oracle_server FOREIGN DATA WRAPPER
oracle_fdw OPTIONS (dbserver 'ORACLE_DBNAME');
CREATE USER MAPPING FOR CURRENT_USER
SERVER oracle_server
OPTIONS (user 'scott', password 'tiger');
CREATE FOREIGN TABLE fdw_test (
userid

numeric,

username

text,

email

text

)
SERVER oracle_server
OPTIONS ( schema 'scott', table 'fdw_test');
postgres=# select * from fdw_test;
userid | username |

email

--------+----------+------------------1 | scott
(1 row)

| scott@oracle.com
NoSQL Wrappers
●

MongoDB

●

Redis

●

CouchDB

●

Neo4j

●

MonetDB

●

Tycoon
NoSQL Wrappers
CREATE SERVER mongo_server FOREIGN DATA WRAPPER
mongo_fdw OPTIONS (address '192.168.122.47', port '27017');
CREATE FOREIGN TABLE databases (
_id NAME,
name TEXT
)
SERVER mongo_server
OPTIONS (database 'mydb', collection 'pgData');
test=# select * from databases ;
_id

|

name

--------------------------+-----------52fd49bfba3ae4ea54afc459 | mongo
52fd49bfba3ae4ea54afc45a | postgresql
52fd49bfba3ae4ea54afc45b | oracle
52fd49bfba3ae4ea54afc45c | mysql
52fd49bfba3ae4ea54afc45d | redis
52fd49bfba3ae4ea54afc45e | db2
(6 rows)
File Wrappers
●

Delimited files

●

Fixed length files

●

JSON files
File Wrappers
CREATE SERVER pg_load FOREIGN DATA WRAPPER file_fdw;
CREATE FOREIGN TABLE leads (
first_name text, last_name text,
company_name text, address text,
city text, county text,
state text, zip text,
phone1 text, phone2 text,
email text, web text
) SERVER pg_load
OPTIONS ( filename '/tmp/us-500.csv', format 'csv', header 'TRUE' );
test=# select first_name || ' ' || last_name as full_name, email from leads limit 3;
full_name

|

email

-------------------+------------------------------James Butt

| jbutt@gmail.com

Josephine Darakjy | josephine_darakjy@darakjy.org
Art Venere
(3 rows)

| art@venere.org
Miscellaneous Wrappers
●

Hadoop

●

LDAP

●

S3

●

WWW

●

PG-Strom
Hadoop Wrapper
CREATE SERVER hive_server FOREIGN DATA WRAPPER
hive_fdw OPTIONS (address '127.0.0.1', port '10000');
CREATE USER MAPPING

FOR PUBLIC SERVER hive_server;

CREATE FOREIGN TABLE order_line (
ol_w_id

integer,

ol_d_id

integer,

ol_o_id

integer,

ol_number

integer,

ol_i_id

integer,

ol_delivery_d

timestamp,

ol_amount

decimal(6,2),

ol_supply_w_id

integer,

ol_quantity

decimal(2,0),

ol_dist_info

varchar(24)

) SERVER hive_server OPTIONS (table 'order_line');
INSERT INTO item_sale_month
SELECT ol_i_id as i_id,
EXTRACT(YEAR FROM ol_delivery_d) as year,
EXTRACT(MONTH FROM ol_delivery_d) as month,
sum(ol_amount) as amount
FROM order_line
GROUP BY 1, 2, 3;
Hadoop Wrapper
●

Hadoop foreign tables can also be writable
CREATE FORIEGN TABLE audit (
audit_id

bigint,

event_d

timestamp,

table

varchar,

action

varchar,

user

varchar,

) SERVER hive_server
OPTIONS (table 'audit',
flume_port '44444');
INSERT INTO audit
VALUES (nextval('audit_id_seq'), now(), 'users', 'SELECT', 'scott');
Hadoop Wrapper
●

It also works with HBase tables
CREATE FOREIGN TABLE hive_hbase_table (
key

varchar,

value varchar
) SERVER localhive
OPTIONS (table 'hbase_table', hbase_address 'localhost',
hbase_port '9090', hbase_mapping ':key,cf:val');
INSERT INTO hive_hbase_table VALUES ('key1', 'value1');
INSERT INTO hive_hbase_table VALUES ('key2', 'value2');
UPDATE hive_hbase_table SET value = 'update' WHERE key = 'key2';
DELETE FROM hive_hbase_table WHERE key='key1';
SELECT * from hive_hbase_table;
WWW Wrapper
CREATE SERVER www_fdw_server_google_search FOREIGN DATA WRAPPER www_fdw
OPTIONS (uri 'https://ajax.googleapis.com/ajax/services/search/web?v=1.0');
CREATE USER MAPPING FOR current_user SERVER www_fdw_server_google_search;
CREATE FOREIGN TABLE www_fdw_google_search (
q text, GsearchResultClass text, unescapedUrl text, url text,
visibleUrl text, cacheUrl text, title text, titleNoFormatting text, content text
) SERVER www_fdw_server_google_search;
select url,substring(title,1,25)||'...',substring(content,1,25)||'...'
from www_fdw_google_search where q='postgresql fdw';
url

|

?column?

|

?column?

-------------------------------------------------------------+------------------------------+-----------------------------http://wiki.postgresql.org/wiki/Foreign_data_wrappers

| Foreign data wrappers - <... | Jan 24, 2014 <b>...</b> 1...

http://www.postgresql.org/docs/9.3/static/postgres-fdw.html | <b>PostgreSQL</b>: Docume... | F.31.1. <b>FDW</b> Option...
http://www.postgresql.org/docs/9.3/static/fdwhandler.html

| <b>PostgreSQL</b>: Docume... | Foreign Data Wrapper Call...

http://www.craigkerstiens.com/2013/08/05/a-look-at-FDWs/

| A look at Foreign Data Wr... | Aug 5, 2013 <b>...</b> An...

(4 rows)
PostgreSQL Wrapper
●

The most functional FDW by far

●

Replaces much of the functionality of dblink

●

Shipped as a contrib module
PostgreSQL Wrapper
CREATE SERVER postgres_server FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'localhost', port '5432', dbname 'test2');
CREATE USER MAPPING FOR PUBLIC SERVER postgres_server;
CREATE FOREIGN TABLE bird_strikes (
aircraft_type varchar, airport varchar, altitude varchar, aircraft_model varchar,
num_wildlife_struck varchar, impact_to_flight varchar, effect varchar,
location varchar, flight_num varchar, flight_date timestamp,
record_id int, indicated_damage varchar, freeform_en_route varchar, num_engines varchar,
airline varchar, origin_state varchar, phase_of_flight varchar, precipitation varchar,
wildlife_collected boolean, wildlife_sent_to_smithsonian boolean, remarks varchar,
reported_date timestamp, wildlife_size varchar, sky_conditions varchar, wildlife_species varchar,
when_time_hhmm varchar, time_of_day varchar, pilot_warned varchar,
cost_out_of_service varchar, cost_other varchar, cost_repair varchar, cost_total varchar,
miles_from_airport varchar, feet_above_ground varchar, num_human_fatalities integer,
num_injured integer, speed_knots varchar
) SERVER postgres_server OPTIONS (table_name 'bird_strikes');
PostgreSQL Wrapper
●

Only requests columns that are needed
test=# explain verbose select airport, flight_date from bird_strikes;
QUERY PLAN
------------------------------------------------------------------------------Foreign Scan on public.bird_strikes

(cost=100.00..148.40 rows=1280 width=40)

Output: airport, flight_date
Remote SQL: SELECT airport, flight_date FROM public.bird_strikes
(3 rows)
PostgreSQL Wrapper
●

Sends a WHERE clause
test=# explain verbose select airport, flight_date from
bird_strikes where flight_date > '2011-01-01';
QUERY PLAN
-----------------------------------------------------------------Foreign Scan on public.bird_strikes
rows=427 width=40)

(cost=100.00..134.54

Output: airport, flight_date
Remote SQL: SELECT airport, flight_date FROM
public.bird_strikes WHERE ((flight_date > '2011-01-01
00:00:00'::timestamp without time zone))
(3 rows)
PostgreSQL Wrapper
●

Sends built-in immutable functions
test=# explain verbose select airport, flight_date from bird_strikes where flight_date
> '2011-01-01' and length(airport) < 10;
QUERY PLAN
------------------------------------------------------------------------------Foreign Scan on public.bird_strikes

(cost=100.00..135.24 rows=142 width=40)

Output: airport, flight_date
Remote SQL: SELECT airport, flight_date FROM public.bird_strikes WHERE ((flight_date
> '2011-01-01 00:00:00'::timestamp without time zone)) AND ((length(airport) < 10))
(3 rows)
PostgreSQL Wrapper
●

Writable (INSERT, UPDATE, DELETE)
test=# explain verbose update bird_strikes set airport = 'Unknown' where record_id = 313339;
QUERY PLAN
------------------------------------------------------------------------------Update on public.bird_strikes

(cost=100.00..111.05 rows=1 width=964)

Remote SQL: UPDATE public.bird_strikes SET airport = $2 WHERE ctid = $1
->

Foreign Scan on public.bird_strikes

(cost=100.00..111.05 rows=1 width=964)

Output: aircraft_type, 'Unknown'::character varying, altitude, aircraft_model, num_wildlife_struck,
impact_to_flight, effect, location, flight_num, flight_date, record_id, indicated_damage, freefo
rm_en_route, num_engines, airline, origin_state, phase_of_flight, precipitation, wildlife_collected,
wildlife_sent_to_smithsonian, remarks, reported_date, wildlife_size, sky_conditions, wildlife_species, w
hen_time_hhmm, time_of_day, pilot_warned, cost_out_of_service, cost_other, cost_repair, cost_total, miles_from_airport,
feet_above_ground, num_human_fatalities, num_injured, speed_knots, ctid
Remote SQL: SELECT aircraft_type, altitude, aircraft_model, num_wildlife_struck, impact_to_flight, effect,
location, flight_num, flight_date, record_id, indicated_damage, freeform_en_route, num_en
gines, airline, origin_state, phase_of_flight, precipitation, wildlife_collected, wildlife_sent_to_smithsonian, remarks,
reported_date, wildlife_size, sky_conditions, wildlife_species, when_time_hhmm, time
_of_day, pilot_warned, cost_out_of_service, cost_other, cost_repair, cost_total, miles_from_airport, feet_above_ground,
num_human_fatalities, num_injured, speed_knots, ctid FROM public.bird_strikes WHERE (
(record_id = 313339)) FOR UPDATE
(5 rows)
PostgreSQL Wrapper
●

Writes are transactional
test=# select airport from bird_strikes where record_id = 313339;
airport
--------Unknown
(1 row)
test=# BEGIN;
BEGIN
test=# update bird_strikes set airport = 'UNKNOWN' where record_id = 313339;
UPDATE 1
test=# ROLLBACK;
ROLLBACK
test=# select airport from bird_strikes where record_id = 313339;
airport
--------Unknown
(1 row)
Limitations
●

Aggregates are not pushed down
test=# explain verbose select count(*) from bird_strikes;
QUERY PLAN
--------------------------------------------------------------------------------------------------------Aggregate

(cost=220.92..220.93 rows=1 width=0)

Output: count(*)
->

Foreign Scan on public.bird_strikes

(cost=100.00..212.39 rows=3413 width=0)

Output: aircraft_type, airport, altitude, aircraft_model, num_wildlife_struck, impact_to_flight, effect,
location, flight_num, flight_date, record_id, indicated_damage, freeform_en_route, num_engi
nes, airline, origin_state, phase_of_flight, precipitation, wildlife_collected, wildlife_sent_to_smithsonian,
remarks, reported_date, wildlife_size, sky_conditions, wildlife_species, when_time_hhmm, time_o
f_day, pilot_warned, cost_out_of_service, cost_other, cost_repair, cost_total, miles_from_airport,
feet_above_ground, num_human_fatalities, num_injured, speed_knots
Remote SQL: SELECT NULL FROM public.bird_strikes
(5 rows)
Limitations
●

ORDER BY, GROUP BY, LIMIT not pushed down
test=# explain verbose select flight_num from bird_strikes order by flight_date limit 5;
QUERY PLAN
------------------------------------------------------------------------------------------Limit

(cost=169.66..169.67 rows=5 width=40)

Output: flight_num, flight_date
->

Sort

(cost=169.66..172.86 rows=1280 width=40)

Output: flight_num, flight_date
Sort Key: bird_strikes.flight_date
->

Foreign Scan on public.bird_strikes

(cost=100.00..148.40 rows=1280 width=40)

Output: flight_num, flight_date
Remote SQL: SELECT flight_num, flight_date FROM public.bird_strikes
(8 rows)
Limitations
●

Joins not pushed down
test=# explain verbose select s.name, b.flight_date
test-# from bird_strikes b, state_code s
test-# where b.location = s.abbreviation and flight_date > '2011-01-01';
QUERY PLAN
------------------------------------------------------------------------------Hash Join

(cost=239.88..349.95 rows=1986 width=40)

Output: s.name, b.flight_date
Hash Cond: ((s.abbreviation)::text = (b.location)::text)
->

Foreign Scan on public.state_code s

(cost=100.00..137.90 rows=930 width=64)

Output: s.id, s.name, s.abbreviation, s.country, s.type, s.sort, s.status, s.occupied, s.notes, s.fips_state, s.assoc_press,
s.standard_federal_region, s.census_region, s.census_region_name, s.cen
sus_division, s.census_devision_name, s.circuit_court
Remote SQL: SELECT name, abbreviation FROM public.state_code
->

Hash

(cost=134.54..134.54 rows=427 width=40)

Output: b.flight_date, b.location
->

Foreign Scan on public.bird_strikes b

(cost=100.00..134.54 rows=427 width=40)

Output: b.flight_date, b.location
Remote SQL: SELECT location, flight_date FROM public.bird_strikes WHERE ((flight_date > '2011-01-01 00:00:00'::timestamp
without time zone))
(11 rows)
Limitations (Gotcha)
●

Sometimes the foreign tables don't act like tables
test=# SELECT l.*, w.lat, w.lng
FROM leads l, www_fdw_geocoder_google w
WHERE w.address = l.address || ',' || l.city || ',' || l.state;
first_name | last_name | company_name | address | city | county |
state | zip | phone1 | phone2 | email | web | lat | lng
------------+-----------+--------------+---------+------+-------+-------+-----+--------+--------+-------+-----+-----+----(0 rows)
Limitations (Gotcha)
QUERY PLAN
------------------------------------------------------------------------------------------Merge Join

(cost=187.47..215.47 rows=1000 width=448)

Output: l.first_name, l.last_name, l.company_name, l.address, l.city, l.county, l.state, l.zip, l.phone1, l.phone2, l.email, l.web, w.lat,
w.lng
Merge Cond: ((((((l.address || ','::text) || l.city) || ','::text) || l.state)) = w.address)
->

Sort

(cost=37.64..38.14 rows=200 width=384)

Output: l.first_name, l.last_name, l.company_name, l.address, l.city, l.county, l.state, l.zip, l.phone1, l.phone2, l.email, l.web,
(((((l.address || ','::text) || l.city) || ','::text) || l.state
))
Sort Key: (((((l.address || ','::text) || l.city) || ','::text) || l.state))
->

Foreign Scan on public.leads l

(cost=0.00..30.00 rows=200 width=384)

Output: l.first_name, l.last_name, l.company_name, l.address, l.city, l.county, l.state, l.zip, l.phone1, l.phone2, l.email,
l.web, ((((l.address || ','::text) || l.city) || ','::text) || l.
state)
Foreign File: /tmp/us-500.csv
Foreign File Size: 81485
->

Sort

(cost=149.83..152.33 rows=1000 width=96)

Output: w.lat, w.lng, w.address
Sort Key: w.address
->

Foreign Scan on public.www_fdw_geocoder_google w
Output: w.lat, w.lng, w.address
WWW API: Request

(16 rows)

(cost=0.00..100.00 rows=1000 width=96)
Limitations (Gotcha)
CREATE OR REPLACE FUNCTION google_geocode(
OUT first_name text, OUT last_name text, OUT company_name text, OUT address text, OUT city text, OUT county text,
OUT state text, OUT zip text, OUT phone1 text, OUT phone2 text, OUT email text, OUT web text, OUT lat text, OUT lng text)
RETURNS SETOF RECORD AS $$
DECLARE
r

record;

f_adr text;
l_lat text;
l_lng text;
BEGIN
FOR r IN SELECT * FROM leads LOOP
f_adr := r.address || ',' || r.city || ',' || r.state;
EXECUTE 'SELECT lat, lng FROM www_fdw_geocoder_google WHERE address = $1'
INTO l_lat, l_lng
USING f_adr;
SELECT

r.first_name, r.last_name, r.company_name, r.address, r.city, r.county, r.state, r.zip,
r.phone1, r.phone2, r.email, r.web, l_lat, l_lng

INTO first_name, last_name, company_name, address, city, county, state, zip,
phone1, phone2, email, web, lat, lng;
RETURN NEXT;
END LOOP;
END $$ LANGUAGE plpgsql;
Writing a new FDW
●

Might not need to write one if there is a http interface

●

Use the Blackhole as a template
–

https://bitbucket.org/adunstan/blackhole_fdw
Writing a new FDW
Datum blackhole_fdw_handler(PG_FUNCTION_ARGS){
...
/* these are required */
fdwroutine->GetForeignRelSize = blackholeGetForeignRelSize;
fdwroutine->GetForeignPaths = blackholeGetForeignPaths;
fdwroutine->GetForeignPlan = blackholeGetForeignPlan;
fdwroutine->BeginForeignScan = blackholeBeginForeignScan;
fdwroutine->IterateForeignScan = blackholeIterateForeignScan;
fdwroutine->ReScanForeignScan = blackholeReScanForeignScan;
fdwroutine->EndForeignScan = blackholeEndForeignScan;
/* remainder are optional - use NULL if not required */
/* support for insert / update / delete */
fdwroutine->AddForeignUpdateTargets = blackholeAddForeignUpdateTargets;
fdwroutine->PlanForeignModify = blackholePlanForeignModify;
fdwroutine->BeginForeignModify = blackholeBeginForeignModify;
fdwroutine->ExecForeignInsert = blackholeExecForeignInsert;
fdwroutine->ExecForeignUpdate = blackholeExecForeignUpdate;
fdwroutine->ExecForeignDelete = blackholeExecForeignDelete;
fdwroutine->EndForeignModify = blackholeEndForeignModify;
/* support for EXPLAIN */
fdwroutine->ExplainForeignScan = blackholeExplainForeignScan;
fdwroutine->ExplainForeignModify = blackholeExplainForeignModify;
/* support for ANALYSE */
fdwroutine->AnalyzeForeignTable = blackholeAnalyzeForeignTable;
PG_RETURN_POINTER(fdwroutine);
}
Future
●

Even more Wrappers

●

Check Constraints on Foreign Tables
–

●

Allows partitioning

Joins
–

Custom Scan API
●

Probably will not be the way to do this, but progress being made
Questions?
jimm@openscg.com
@jim_mlodgenski

More Related Content

KEY
PostgreSQL
PDF
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
PPTX
Cloud Native PostgreSQL
 
PDF
New features in ProxySQL 2.0 (updated to 2.0.9) by Rene Cannao (ProxySQL)
PDF
PostgreSQL Performance Tuning
PDF
Mastering PostgreSQL Administration
 
PDF
Deep Dive on ClickHouse Sharding and Replication-2202-09-22.pdf
PDF
Aws glue를 통한 손쉬운 데이터 전처리 작업하기
PostgreSQL
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
Cloud Native PostgreSQL
 
New features in ProxySQL 2.0 (updated to 2.0.9) by Rene Cannao (ProxySQL)
PostgreSQL Performance Tuning
Mastering PostgreSQL Administration
 
Deep Dive on ClickHouse Sharding and Replication-2202-09-22.pdf
Aws glue를 통한 손쉬운 데이터 전처리 작업하기

What's hot (20)

PDF
Understanding the architecture of MariaDB ColumnStore
PPTX
bigquery.pptx
PDF
AWS CLOUD 2017 - Amazon Athena 및 Glue를 통한 빠른 데이터 질의 및 처리 기능 소개 (김상필 솔루션즈 아키텍트)
ODP
PostgreSQL Administration for System Administrators
PDF
AWS Fargate와 Amazon ECS를 활용한 CI/CD 모범사례 - 유재석, AWS 솔루션즈 아키텍트 :: AWS Game Mast...
PDF
All about Zookeeper and ClickHouse Keeper.pdf
PDF
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
PDF
Linux tuning to improve PostgreSQL performance
PDF
MySQL developing Store Procedure
PPTX
Mongo DB 성능최적화 전략
PPT
Ash masters : advanced ash analytics on Oracle
PDF
사례로 알아보는 Database Migration Service : 데이터베이스 및 데이터 이관, 통합, 분리, 분석의 도구 - 발표자: ...
PDF
[2019] 200만 동접 게임을 위한 MySQL 샤딩
PDF
AWS Summit Seoul 2023 | 실시간 CDC 데이터 처리! Modern Transactional Data Lake 구축하기
PDF
Deep dive into PostgreSQL statistics.
PDF
Amazon VPC와 ELB/Direct Connect/VPN 알아보기 - 김세준, AWS 솔루션즈 아키텍트
PDF
천만 사용자를 위한 AWS 클라우드 아키텍처 진화하기::이창수::AWS Summit Seoul 2018
PDF
데이터베이스 운영, 서버리스로 걱정 끝! - 윤석찬, AWS 테크에반젤리스트 - AWS Builders Online Series
PDF
실시간 스트리밍 분석 Kinesis Data Analytics Deep Dive
PDF
MariaDB MaxScale monitor 매뉴얼
Understanding the architecture of MariaDB ColumnStore
bigquery.pptx
AWS CLOUD 2017 - Amazon Athena 및 Glue를 통한 빠른 데이터 질의 및 처리 기능 소개 (김상필 솔루션즈 아키텍트)
PostgreSQL Administration for System Administrators
AWS Fargate와 Amazon ECS를 활용한 CI/CD 모범사례 - 유재석, AWS 솔루션즈 아키텍트 :: AWS Game Mast...
All about Zookeeper and ClickHouse Keeper.pdf
Amazon OpenSearch Deep dive - 내부구조, 성능최적화 그리고 스케일링
Linux tuning to improve PostgreSQL performance
MySQL developing Store Procedure
Mongo DB 성능최적화 전략
Ash masters : advanced ash analytics on Oracle
사례로 알아보는 Database Migration Service : 데이터베이스 및 데이터 이관, 통합, 분리, 분석의 도구 - 발표자: ...
[2019] 200만 동접 게임을 위한 MySQL 샤딩
AWS Summit Seoul 2023 | 실시간 CDC 데이터 처리! Modern Transactional Data Lake 구축하기
Deep dive into PostgreSQL statistics.
Amazon VPC와 ELB/Direct Connect/VPN 알아보기 - 김세준, AWS 솔루션즈 아키텍트
천만 사용자를 위한 AWS 클라우드 아키텍처 진화하기::이창수::AWS Summit Seoul 2018
데이터베이스 운영, 서버리스로 걱정 끝! - 윤석찬, AWS 테크에반젤리스트 - AWS Builders Online Series
실시간 스트리밍 분석 Kinesis Data Analytics Deep Dive
MariaDB MaxScale monitor 매뉴얼
Ad

Similar to Postgresql Federation (20)

PDF
2013 Collaborate - OAUG - Presentation
PPT
Leveraging Hadoop in your PostgreSQL Environment
PDF
ProxySQL and the Tricks Up Its Sleeve - Percona Live 2022.pdf
PDF
Codepot - Pig i Hive: szybkie wprowadzenie / Pig and Hive crash course
PDF
Search@airbnb
PDF
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PPTX
Drupal 8 migrate!
PDF
SF Big Analytics 20191112: How to performance-tune Spark applications in larg...
PDF
Troubleshooting PostgreSQL Streaming Replication
PDF
Presto anatomy
PDF
Application Monitoring using Open Source - VictoriaMetrics & Altinity ClickHo...
PDF
Application Monitoring using Open Source: VictoriaMetrics - ClickHouse
PDF
MySQL Workbench for DFW Unix Users Group
PDF
Creating PostgreSQL-as-a-Service at Scale
PDF
JavaScript client API for Google Apps Script API primer
PDF
OQGraph @ SCaLE 11x 2013
PDF
[245] presto 내부구조 파헤치기
PDF
FOSDEM 2012: MySQL synchronous replication in practice with Galera
PPTX
Love Your Database Railsconf 2017
PDF
PostgreSQL - масштабирование в моде, Valentine Gogichashvili (Zalando SE)
2013 Collaborate - OAUG - Presentation
Leveraging Hadoop in your PostgreSQL Environment
ProxySQL and the Tricks Up Its Sleeve - Percona Live 2022.pdf
Codepot - Pig i Hive: szybkie wprowadzenie / Pig and Hive crash course
Search@airbnb
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
Drupal 8 migrate!
SF Big Analytics 20191112: How to performance-tune Spark applications in larg...
Troubleshooting PostgreSQL Streaming Replication
Presto anatomy
Application Monitoring using Open Source - VictoriaMetrics & Altinity ClickHo...
Application Monitoring using Open Source: VictoriaMetrics - ClickHouse
MySQL Workbench for DFW Unix Users Group
Creating PostgreSQL-as-a-Service at Scale
JavaScript client API for Google Apps Script API primer
OQGraph @ SCaLE 11x 2013
[245] presto 내부구조 파헤치기
FOSDEM 2012: MySQL synchronous replication in practice with Galera
Love Your Database Railsconf 2017
PostgreSQL - масштабирование в моде, Valentine Gogichashvili (Zalando SE)
Ad

More from Jim Mlodgenski (10)

PDF
Strategic autovacuum
PDF
Top 10 Mistakes When Migrating From Oracle to PostgreSQL
PDF
Oracle postgre sql-mirgration-top-10-mistakes
PDF
Profiling PL/pgSQL
PDF
Debugging Your PL/pgSQL Code
PDF
An Introduction To PostgreSQL Triggers
ODP
Introduction to PostgreSQL
PDF
Scaling PostreSQL with Stado
ODP
Multi-Master Replication with Slony
ODP
Scaling PostgreSQL With GridSQL
Strategic autovacuum
Top 10 Mistakes When Migrating From Oracle to PostgreSQL
Oracle postgre sql-mirgration-top-10-mistakes
Profiling PL/pgSQL
Debugging Your PL/pgSQL Code
An Introduction To PostgreSQL Triggers
Introduction to PostgreSQL
Scaling PostreSQL with Stado
Multi-Master Replication with Slony
Scaling PostgreSQL With GridSQL

Recently uploaded (20)

PDF
Spectral efficient network and resource selection model in 5G networks
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
cuic standard and advanced reporting.pdf
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
Big Data Technologies - Introduction.pptx
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
A Presentation on Artificial Intelligence
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Machine learning based COVID-19 study performance prediction
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Spectral efficient network and resource selection model in 5G networks
The Rise and Fall of 3GPP – Time for a Sabbatical?
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
cuic standard and advanced reporting.pdf
20250228 LYD VKU AI Blended-Learning.pptx
Big Data Technologies - Introduction.pptx
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
A Presentation on Artificial Intelligence
Per capita expenditure prediction using model stacking based on satellite ima...
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
The AUB Centre for AI in Media Proposal.docx
Building Integrated photovoltaic BIPV_UPV.pdf
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
MYSQL Presentation for SQL database connectivity
Diabetes mellitus diagnosis method based random forest with bat algorithm
Machine learning based COVID-19 study performance prediction
Network Security Unit 5.pdf for BCA BBA.
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf

Postgresql Federation

  • 2. Who Am I? ● Jim Mlodgenski – – ● jimm@openscg.com @jim_mlodgenski Co-organizer of – – ● NYC PUG (www.nycpug.org) Philly PUG (www.phlpug.org) CTO, OpenSCG – www.openscg.com
  • 4. What is a federated database? “A federated database system is a type of meta-database management system (DBMS), which transparently maps multiple autonomous database systems into a single federated database. The constituent databases are interconnected via a computer network and may be geographically decentralized. ... There is no actual data integration in the constituent disparate databases as a result of data federation.” -Wikipedia
  • 5. How does PostgreSQL do it? ● Uses Foreign Table Wrappers (FDW) ● Used with SQL/MED – – Management of External Data – ● New ANIS SQL 2003 Extension Standard way of handling remote objects in SQL databases Wrappers used by SQL/MED to access remotes data sources
  • 6. Types of Foreign Data Wrappers ● SQL ● NoSQL ● File ● Miscellaneous ● PostgreSQL
  • 8. SQL Wrappers CREATE SERVER oracle_server FOREIGN DATA WRAPPER oracle_fdw OPTIONS (dbserver 'ORACLE_DBNAME'); CREATE USER MAPPING FOR CURRENT_USER SERVER oracle_server OPTIONS (user 'scott', password 'tiger'); CREATE FOREIGN TABLE fdw_test ( userid numeric, username text, email text ) SERVER oracle_server OPTIONS ( schema 'scott', table 'fdw_test'); postgres=# select * from fdw_test; userid | username | email --------+----------+------------------1 | scott (1 row) | scott@oracle.com
  • 10. NoSQL Wrappers CREATE SERVER mongo_server FOREIGN DATA WRAPPER mongo_fdw OPTIONS (address '192.168.122.47', port '27017'); CREATE FOREIGN TABLE databases ( _id NAME, name TEXT ) SERVER mongo_server OPTIONS (database 'mydb', collection 'pgData'); test=# select * from databases ; _id | name --------------------------+-----------52fd49bfba3ae4ea54afc459 | mongo 52fd49bfba3ae4ea54afc45a | postgresql 52fd49bfba3ae4ea54afc45b | oracle 52fd49bfba3ae4ea54afc45c | mysql 52fd49bfba3ae4ea54afc45d | redis 52fd49bfba3ae4ea54afc45e | db2 (6 rows)
  • 11. File Wrappers ● Delimited files ● Fixed length files ● JSON files
  • 12. File Wrappers CREATE SERVER pg_load FOREIGN DATA WRAPPER file_fdw; CREATE FOREIGN TABLE leads ( first_name text, last_name text, company_name text, address text, city text, county text, state text, zip text, phone1 text, phone2 text, email text, web text ) SERVER pg_load OPTIONS ( filename '/tmp/us-500.csv', format 'csv', header 'TRUE' ); test=# select first_name || ' ' || last_name as full_name, email from leads limit 3; full_name | email -------------------+------------------------------James Butt | jbutt@gmail.com Josephine Darakjy | josephine_darakjy@darakjy.org Art Venere (3 rows) | art@venere.org
  • 14. Hadoop Wrapper CREATE SERVER hive_server FOREIGN DATA WRAPPER hive_fdw OPTIONS (address '127.0.0.1', port '10000'); CREATE USER MAPPING FOR PUBLIC SERVER hive_server; CREATE FOREIGN TABLE order_line ( ol_w_id integer, ol_d_id integer, ol_o_id integer, ol_number integer, ol_i_id integer, ol_delivery_d timestamp, ol_amount decimal(6,2), ol_supply_w_id integer, ol_quantity decimal(2,0), ol_dist_info varchar(24) ) SERVER hive_server OPTIONS (table 'order_line'); INSERT INTO item_sale_month SELECT ol_i_id as i_id, EXTRACT(YEAR FROM ol_delivery_d) as year, EXTRACT(MONTH FROM ol_delivery_d) as month, sum(ol_amount) as amount FROM order_line GROUP BY 1, 2, 3;
  • 15. Hadoop Wrapper ● Hadoop foreign tables can also be writable CREATE FORIEGN TABLE audit ( audit_id bigint, event_d timestamp, table varchar, action varchar, user varchar, ) SERVER hive_server OPTIONS (table 'audit', flume_port '44444'); INSERT INTO audit VALUES (nextval('audit_id_seq'), now(), 'users', 'SELECT', 'scott');
  • 16. Hadoop Wrapper ● It also works with HBase tables CREATE FOREIGN TABLE hive_hbase_table ( key varchar, value varchar ) SERVER localhive OPTIONS (table 'hbase_table', hbase_address 'localhost', hbase_port '9090', hbase_mapping ':key,cf:val'); INSERT INTO hive_hbase_table VALUES ('key1', 'value1'); INSERT INTO hive_hbase_table VALUES ('key2', 'value2'); UPDATE hive_hbase_table SET value = 'update' WHERE key = 'key2'; DELETE FROM hive_hbase_table WHERE key='key1'; SELECT * from hive_hbase_table;
  • 17. WWW Wrapper CREATE SERVER www_fdw_server_google_search FOREIGN DATA WRAPPER www_fdw OPTIONS (uri 'https://ajax.googleapis.com/ajax/services/search/web?v=1.0'); CREATE USER MAPPING FOR current_user SERVER www_fdw_server_google_search; CREATE FOREIGN TABLE www_fdw_google_search ( q text, GsearchResultClass text, unescapedUrl text, url text, visibleUrl text, cacheUrl text, title text, titleNoFormatting text, content text ) SERVER www_fdw_server_google_search; select url,substring(title,1,25)||'...',substring(content,1,25)||'...' from www_fdw_google_search where q='postgresql fdw'; url | ?column? | ?column? -------------------------------------------------------------+------------------------------+-----------------------------http://wiki.postgresql.org/wiki/Foreign_data_wrappers | Foreign data wrappers - <... | Jan 24, 2014 <b>...</b> 1... http://www.postgresql.org/docs/9.3/static/postgres-fdw.html | <b>PostgreSQL</b>: Docume... | F.31.1. <b>FDW</b> Option... http://www.postgresql.org/docs/9.3/static/fdwhandler.html | <b>PostgreSQL</b>: Docume... | Foreign Data Wrapper Call... http://www.craigkerstiens.com/2013/08/05/a-look-at-FDWs/ | A look at Foreign Data Wr... | Aug 5, 2013 <b>...</b> An... (4 rows)
  • 18. PostgreSQL Wrapper ● The most functional FDW by far ● Replaces much of the functionality of dblink ● Shipped as a contrib module
  • 19. PostgreSQL Wrapper CREATE SERVER postgres_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'localhost', port '5432', dbname 'test2'); CREATE USER MAPPING FOR PUBLIC SERVER postgres_server; CREATE FOREIGN TABLE bird_strikes ( aircraft_type varchar, airport varchar, altitude varchar, aircraft_model varchar, num_wildlife_struck varchar, impact_to_flight varchar, effect varchar, location varchar, flight_num varchar, flight_date timestamp, record_id int, indicated_damage varchar, freeform_en_route varchar, num_engines varchar, airline varchar, origin_state varchar, phase_of_flight varchar, precipitation varchar, wildlife_collected boolean, wildlife_sent_to_smithsonian boolean, remarks varchar, reported_date timestamp, wildlife_size varchar, sky_conditions varchar, wildlife_species varchar, when_time_hhmm varchar, time_of_day varchar, pilot_warned varchar, cost_out_of_service varchar, cost_other varchar, cost_repair varchar, cost_total varchar, miles_from_airport varchar, feet_above_ground varchar, num_human_fatalities integer, num_injured integer, speed_knots varchar ) SERVER postgres_server OPTIONS (table_name 'bird_strikes');
  • 20. PostgreSQL Wrapper ● Only requests columns that are needed test=# explain verbose select airport, flight_date from bird_strikes; QUERY PLAN ------------------------------------------------------------------------------Foreign Scan on public.bird_strikes (cost=100.00..148.40 rows=1280 width=40) Output: airport, flight_date Remote SQL: SELECT airport, flight_date FROM public.bird_strikes (3 rows)
  • 21. PostgreSQL Wrapper ● Sends a WHERE clause test=# explain verbose select airport, flight_date from bird_strikes where flight_date > '2011-01-01'; QUERY PLAN -----------------------------------------------------------------Foreign Scan on public.bird_strikes rows=427 width=40) (cost=100.00..134.54 Output: airport, flight_date Remote SQL: SELECT airport, flight_date FROM public.bird_strikes WHERE ((flight_date > '2011-01-01 00:00:00'::timestamp without time zone)) (3 rows)
  • 22. PostgreSQL Wrapper ● Sends built-in immutable functions test=# explain verbose select airport, flight_date from bird_strikes where flight_date > '2011-01-01' and length(airport) < 10; QUERY PLAN ------------------------------------------------------------------------------Foreign Scan on public.bird_strikes (cost=100.00..135.24 rows=142 width=40) Output: airport, flight_date Remote SQL: SELECT airport, flight_date FROM public.bird_strikes WHERE ((flight_date > '2011-01-01 00:00:00'::timestamp without time zone)) AND ((length(airport) < 10)) (3 rows)
  • 23. PostgreSQL Wrapper ● Writable (INSERT, UPDATE, DELETE) test=# explain verbose update bird_strikes set airport = 'Unknown' where record_id = 313339; QUERY PLAN ------------------------------------------------------------------------------Update on public.bird_strikes (cost=100.00..111.05 rows=1 width=964) Remote SQL: UPDATE public.bird_strikes SET airport = $2 WHERE ctid = $1 -> Foreign Scan on public.bird_strikes (cost=100.00..111.05 rows=1 width=964) Output: aircraft_type, 'Unknown'::character varying, altitude, aircraft_model, num_wildlife_struck, impact_to_flight, effect, location, flight_num, flight_date, record_id, indicated_damage, freefo rm_en_route, num_engines, airline, origin_state, phase_of_flight, precipitation, wildlife_collected, wildlife_sent_to_smithsonian, remarks, reported_date, wildlife_size, sky_conditions, wildlife_species, w hen_time_hhmm, time_of_day, pilot_warned, cost_out_of_service, cost_other, cost_repair, cost_total, miles_from_airport, feet_above_ground, num_human_fatalities, num_injured, speed_knots, ctid Remote SQL: SELECT aircraft_type, altitude, aircraft_model, num_wildlife_struck, impact_to_flight, effect, location, flight_num, flight_date, record_id, indicated_damage, freeform_en_route, num_en gines, airline, origin_state, phase_of_flight, precipitation, wildlife_collected, wildlife_sent_to_smithsonian, remarks, reported_date, wildlife_size, sky_conditions, wildlife_species, when_time_hhmm, time _of_day, pilot_warned, cost_out_of_service, cost_other, cost_repair, cost_total, miles_from_airport, feet_above_ground, num_human_fatalities, num_injured, speed_knots, ctid FROM public.bird_strikes WHERE ( (record_id = 313339)) FOR UPDATE (5 rows)
  • 24. PostgreSQL Wrapper ● Writes are transactional test=# select airport from bird_strikes where record_id = 313339; airport --------Unknown (1 row) test=# BEGIN; BEGIN test=# update bird_strikes set airport = 'UNKNOWN' where record_id = 313339; UPDATE 1 test=# ROLLBACK; ROLLBACK test=# select airport from bird_strikes where record_id = 313339; airport --------Unknown (1 row)
  • 25. Limitations ● Aggregates are not pushed down test=# explain verbose select count(*) from bird_strikes; QUERY PLAN --------------------------------------------------------------------------------------------------------Aggregate (cost=220.92..220.93 rows=1 width=0) Output: count(*) -> Foreign Scan on public.bird_strikes (cost=100.00..212.39 rows=3413 width=0) Output: aircraft_type, airport, altitude, aircraft_model, num_wildlife_struck, impact_to_flight, effect, location, flight_num, flight_date, record_id, indicated_damage, freeform_en_route, num_engi nes, airline, origin_state, phase_of_flight, precipitation, wildlife_collected, wildlife_sent_to_smithsonian, remarks, reported_date, wildlife_size, sky_conditions, wildlife_species, when_time_hhmm, time_o f_day, pilot_warned, cost_out_of_service, cost_other, cost_repair, cost_total, miles_from_airport, feet_above_ground, num_human_fatalities, num_injured, speed_knots Remote SQL: SELECT NULL FROM public.bird_strikes (5 rows)
  • 26. Limitations ● ORDER BY, GROUP BY, LIMIT not pushed down test=# explain verbose select flight_num from bird_strikes order by flight_date limit 5; QUERY PLAN ------------------------------------------------------------------------------------------Limit (cost=169.66..169.67 rows=5 width=40) Output: flight_num, flight_date -> Sort (cost=169.66..172.86 rows=1280 width=40) Output: flight_num, flight_date Sort Key: bird_strikes.flight_date -> Foreign Scan on public.bird_strikes (cost=100.00..148.40 rows=1280 width=40) Output: flight_num, flight_date Remote SQL: SELECT flight_num, flight_date FROM public.bird_strikes (8 rows)
  • 27. Limitations ● Joins not pushed down test=# explain verbose select s.name, b.flight_date test-# from bird_strikes b, state_code s test-# where b.location = s.abbreviation and flight_date > '2011-01-01'; QUERY PLAN ------------------------------------------------------------------------------Hash Join (cost=239.88..349.95 rows=1986 width=40) Output: s.name, b.flight_date Hash Cond: ((s.abbreviation)::text = (b.location)::text) -> Foreign Scan on public.state_code s (cost=100.00..137.90 rows=930 width=64) Output: s.id, s.name, s.abbreviation, s.country, s.type, s.sort, s.status, s.occupied, s.notes, s.fips_state, s.assoc_press, s.standard_federal_region, s.census_region, s.census_region_name, s.cen sus_division, s.census_devision_name, s.circuit_court Remote SQL: SELECT name, abbreviation FROM public.state_code -> Hash (cost=134.54..134.54 rows=427 width=40) Output: b.flight_date, b.location -> Foreign Scan on public.bird_strikes b (cost=100.00..134.54 rows=427 width=40) Output: b.flight_date, b.location Remote SQL: SELECT location, flight_date FROM public.bird_strikes WHERE ((flight_date > '2011-01-01 00:00:00'::timestamp without time zone)) (11 rows)
  • 28. Limitations (Gotcha) ● Sometimes the foreign tables don't act like tables test=# SELECT l.*, w.lat, w.lng FROM leads l, www_fdw_geocoder_google w WHERE w.address = l.address || ',' || l.city || ',' || l.state; first_name | last_name | company_name | address | city | county | state | zip | phone1 | phone2 | email | web | lat | lng ------------+-----------+--------------+---------+------+-------+-------+-----+--------+--------+-------+-----+-----+----(0 rows)
  • 29. Limitations (Gotcha) QUERY PLAN ------------------------------------------------------------------------------------------Merge Join (cost=187.47..215.47 rows=1000 width=448) Output: l.first_name, l.last_name, l.company_name, l.address, l.city, l.county, l.state, l.zip, l.phone1, l.phone2, l.email, l.web, w.lat, w.lng Merge Cond: ((((((l.address || ','::text) || l.city) || ','::text) || l.state)) = w.address) -> Sort (cost=37.64..38.14 rows=200 width=384) Output: l.first_name, l.last_name, l.company_name, l.address, l.city, l.county, l.state, l.zip, l.phone1, l.phone2, l.email, l.web, (((((l.address || ','::text) || l.city) || ','::text) || l.state )) Sort Key: (((((l.address || ','::text) || l.city) || ','::text) || l.state)) -> Foreign Scan on public.leads l (cost=0.00..30.00 rows=200 width=384) Output: l.first_name, l.last_name, l.company_name, l.address, l.city, l.county, l.state, l.zip, l.phone1, l.phone2, l.email, l.web, ((((l.address || ','::text) || l.city) || ','::text) || l. state) Foreign File: /tmp/us-500.csv Foreign File Size: 81485 -> Sort (cost=149.83..152.33 rows=1000 width=96) Output: w.lat, w.lng, w.address Sort Key: w.address -> Foreign Scan on public.www_fdw_geocoder_google w Output: w.lat, w.lng, w.address WWW API: Request (16 rows) (cost=0.00..100.00 rows=1000 width=96)
  • 30. Limitations (Gotcha) CREATE OR REPLACE FUNCTION google_geocode( OUT first_name text, OUT last_name text, OUT company_name text, OUT address text, OUT city text, OUT county text, OUT state text, OUT zip text, OUT phone1 text, OUT phone2 text, OUT email text, OUT web text, OUT lat text, OUT lng text) RETURNS SETOF RECORD AS $$ DECLARE r record; f_adr text; l_lat text; l_lng text; BEGIN FOR r IN SELECT * FROM leads LOOP f_adr := r.address || ',' || r.city || ',' || r.state; EXECUTE 'SELECT lat, lng FROM www_fdw_geocoder_google WHERE address = $1' INTO l_lat, l_lng USING f_adr; SELECT r.first_name, r.last_name, r.company_name, r.address, r.city, r.county, r.state, r.zip, r.phone1, r.phone2, r.email, r.web, l_lat, l_lng INTO first_name, last_name, company_name, address, city, county, state, zip, phone1, phone2, email, web, lat, lng; RETURN NEXT; END LOOP; END $$ LANGUAGE plpgsql;
  • 31. Writing a new FDW ● Might not need to write one if there is a http interface ● Use the Blackhole as a template – https://bitbucket.org/adunstan/blackhole_fdw
  • 32. Writing a new FDW Datum blackhole_fdw_handler(PG_FUNCTION_ARGS){ ... /* these are required */ fdwroutine->GetForeignRelSize = blackholeGetForeignRelSize; fdwroutine->GetForeignPaths = blackholeGetForeignPaths; fdwroutine->GetForeignPlan = blackholeGetForeignPlan; fdwroutine->BeginForeignScan = blackholeBeginForeignScan; fdwroutine->IterateForeignScan = blackholeIterateForeignScan; fdwroutine->ReScanForeignScan = blackholeReScanForeignScan; fdwroutine->EndForeignScan = blackholeEndForeignScan; /* remainder are optional - use NULL if not required */ /* support for insert / update / delete */ fdwroutine->AddForeignUpdateTargets = blackholeAddForeignUpdateTargets; fdwroutine->PlanForeignModify = blackholePlanForeignModify; fdwroutine->BeginForeignModify = blackholeBeginForeignModify; fdwroutine->ExecForeignInsert = blackholeExecForeignInsert; fdwroutine->ExecForeignUpdate = blackholeExecForeignUpdate; fdwroutine->ExecForeignDelete = blackholeExecForeignDelete; fdwroutine->EndForeignModify = blackholeEndForeignModify; /* support for EXPLAIN */ fdwroutine->ExplainForeignScan = blackholeExplainForeignScan; fdwroutine->ExplainForeignModify = blackholeExplainForeignModify; /* support for ANALYSE */ fdwroutine->AnalyzeForeignTable = blackholeAnalyzeForeignTable; PG_RETURN_POINTER(fdwroutine); }
  • 33. Future ● Even more Wrappers ● Check Constraints on Foreign Tables – ● Allows partitioning Joins – Custom Scan API ● Probably will not be the way to do this, but progress being made