Questo è in continuazione del mio precedente post sul blog in cui avevo toccato un argomento delle estensioni di PostgreSQL. Le estensioni PostgreSQL sono un set plug and play di miglioramenti che aggiungono un set di funzionalità extra a un cluster PostgreSQL. Alcune di queste funzionalità sono semplici come leggere o scrivere su un database esterno, mentre altre potrebbero essere una soluzione sofisticata per implementare la replica del database, il monitoraggio, ecc.
PostgreSQL si è evoluto nel corso degli anni da un semplice ORDBMS open source a un potente sistema di database con oltre 30 anni di sviluppo attivo che offre affidabilità, prestazioni e tutte le funzionalità compatibili con ACID. Con PostgreSQL 12 rilasciato alcuni mesi fa, questo software di database sta diventando sempre più grande, migliore e più veloce.
Occasionalmente, le estensioni dovevano essere aggiunte a un cluster PostgreSQL per ottenere funzionalità avanzate che non erano disponibili nel codice nativo, perché non erano state sviluppate a causa di limiti di tempo o per prove insufficienti del database dei casi limite i problemi. Discuterò alcune delle mie estensioni preferite senza un ordine particolare, con alcune demo utilizzate da sviluppatori e DBA.
Alcune di queste estensioni potrebbero richiedere di essere incluse nel parametro del server shared_preload_libraries come un elenco separato da virgole da precaricare all'avvio del server. Sebbene la maggior parte delle estensioni siano incluse nel modulo contrib del codice sorgente, alcune devono essere scaricate da un sito Web esterno dedicato solo alle estensioni PostgreSQL chiamato PostgreSQL Extension Network.
In questa serie di blog in due parti discuteremo delle estensioni utilizzate per accedere ai dati (postgres_fwd) e ridurre o archiviare i database (pg_partman). Ulteriori estensioni saranno discusse nella seconda parte.
postgres_fdw
Postgres_fdw è un'estensione del wrapper di dati esterni che può essere utilizzata per accedere ai dati archiviati in server PostgreSQL esterni. Questa estensione è simile a un'estensione precedente chiamata dblink ma si differenzia dal suo predecessore offrendo una sintassi conforme agli standard e prestazioni migliori.
I componenti importanti di postgres_fdw sono un server, una mappatura utente e una tabella esterna. C'è un sovraccarico minore aggiunto al costo effettivo dell'esecuzione di query sui server remoti che è il sovraccarico di comunicazione. L'estensione postgres_fdw è anche in grado di comunicare con un server remoto con una versione fino a PostgreSQL 8.3, essendo quindi compatibile con le versioni precedenti.
Demo
La demo mostrerà una connessione da PostgreSQL 12 a un database PostgreSQL 11. Le impostazioni pg_hba.conf sono già state configurate per la comunicazione tra i server. I file di controllo delle estensioni devono essere caricati nella home directory condivisa di PostgreSQL prima di creare l'estensione da All'interno di un cluster PostgreSQL.
Server remoto:
$ /usr/local/pgsql-11.3/bin/psql -p 5432 -d db_replica postgres
psql (11.3)
Type "help" for help.
db_replica=# create table t1 (sno integer, emp_id text);
CREATE TABLE
db_replica=# \dt t1
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | t1 | table | postgres
db_replica=# insert into t1 values (1, 'emp_one');
INSERT 0 1
db_replica=# select * from t1;
sno | emp_id
-----+---------
1 | emp_one
(1 row)
Server di origine:
$ /database/pgsql-12.0/bin/psql -p 5732 postgres
psql (12.0)
Type "help" for help.
postgres=# CREATE EXTENSION postgres_fdw;
CREATE EXTENSION
postgres=# CREATE SERVER remote_server
postgres-# FOREIGN DATA WRAPPER postgres_fdw
postgres-# OPTIONS (host '192.168.1.107', port '5432', dbname 'db_replica');
CREATE SERVER
postgres=# CREATE USER MAPPING FOR postgres
postgres-# SERVER remote_server
postgres-# OPTIONS (user 'postgres', password 'admin123');
CREATE USER MAPPING
postgres=# CREATE FOREIGN TABLE remote_t1
postgres-# (sno integer, emp_id text)
postgres-# server remote_server
postgres-# options (schema_name 'public', table_name 't1');
CREATE FOREIGN TABLE
postgres=# select * from remote_t1;
sno | emp_id
-----+---------
1 | emp_one
(1 row)
postgres=# insert into remote_t1 values (2,'emp_two');
INSERT 0 1
postgres=# select * from remote_t1;
sno | emp_id
-----+---------
1 | emp_one
2 | emp_two
(2 rows)
L'operazione di SCRITTURA dal server di origine riflette immediatamente la tabella del server remoto. Esiste anche un'estensione simile chiamata oracle_fdw che consente l'accesso in LETTURA e SCRITTURA tra le tabelle PostgreSQL e Oracle. Oltre a ciò, esiste un'altra estensione chiamata file_fdw che consente l'accesso ai dati da file flat su disco. Fare riferimento alla documentazione ufficiale di postgres_fdw pubblicata qui, per maggiori informazioni e dettagli.
pg_partman
Man mano che i database e le tabelle crescono, è sempre necessario ridurre i database, archiviare i dati che non sono necessari o almeno partizionare le tabelle in vari frammenti più piccoli. In questo modo Query Optimizer visita solo le parti della tabella che soddisfano le condizioni della query, invece di analizzare l'intero heap di tabelle.
PostgreSQL offre da molto tempo funzionalità di partizionamento tra cui tecniche di intervallo, elenco, hash e sottopartizionamento. Tuttavia, richiede molti sforzi di amministrazione e gestione come la definizione di tabelle figlie che ereditano le proprietà di una tabella padre per diventare le sue partizioni, la creazione di funzioni trigger per reindirizzare i dati in una partizione e creare ulteriormente trigger per chiamare tali funzioni, ecc. Questo è dove entra in gioco pg_partman, in cui tutti questi problemi vengono risolti automaticamente.
Demo
Mostrerò una rapida demo dell'impostazione e dell'inserimento di dati campione. Vedrai come i dati inseriti nella tabella principale vengono reindirizzati automaticamente alle partizioni semplicemente impostando pg_partman. È importante che la colonna della chiave di partizione non sia nulla.
db_replica=# show shared_preload_libraries;
shared_preload_libraries
--------------------------
pg_partman_bgw
(1 row)
db_replica=# CREATE SCHEMA partman;
CREATE SCHEMA
db_replica=# CREATE EXTENSION pg_partman SCHEMA partman;
CREATE EXTENSION
db_replica=# CREATE ROLE partman WITH LOGIN;
CREATE ROLE
db_replica=# GRANT ALL ON SCHEMA partman TO partman;
GRANT
db_replica=# GRANT ALL ON ALL TABLES IN SCHEMA partman TO partman;
GRANT
db_replica=# GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA partman TO partman;
GRANT
db_replica=# GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA partman TO partman;
GRANT
db_replica=# GRANT ALL ON SCHEMA PUBLIC TO partman;
GRANT
db_replica=# create table t1 (sno integer, emp_id varchar, date_of_join date not null);
db_replica=# \d
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | t1 | table | postgres
(1 row)
db_replica=# \d t1
Table "public.t1"
Column | Type | Collation | Nullable | Default
--------------+-------------------+-----------+----------+---------
sno | integer | | |
emp_id | character varying | | |
date_of_join | date | | not null |
db_replica=# SELECT partman.create_parent('public.t1', 'date_of_join', 'partman', 'yearly');
create_parent
---------------
t
(1 row)
db_replica=# \d+ t1
Table "public.t1"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------------+-------------------+-----------+----------+---------+----------+--------------+-------------
sno | integer | | | | plain | |
emp_id | character varying | | | | extended | |
date_of_join | date | | not null | | plain | |
Triggers:
t1_part_trig BEFORE INSERT ON t1 FOR EACH ROW EXECUTE PROCEDURE t1_part_trig_func()
Child tables: t1_p2015,
t1_p2016,
t1_p2017,
t1_p2018,
t1_p2019,
t1_p2020,
t1_p2021,
t1_p2022,
t1_p2023
db_replica=# select * from t1;
sno | emp_id | date_of_join
-----+--------+--------------
(0 rows)
db_replica=# select * from t1_p2019;
sno | emp_id | date_of_join
-----+--------+--------------
(0 rows)
db_replica=# select * from t1_p2020;
sno | emp_id | date_of_join
-----+--------+--------------
(0 rows)
db_replica=# insert into t1 values (1,'emp_one','01-06-2019');
INSERT 0 0
db_replica=# insert into t1 values (2,'emp_two','01-06-2020');
INSERT 0 0
db_replica=# select * from t1;
sno | emp_id | date_of_join
-----+---------+--------------
1 | emp_one | 2019-01-06
2 | emp_two | 2020-01-06
(2 rows)
db_replica=# select * from t1_p2019;
sno | emp_id | date_of_join
-----+---------+--------------
1 | emp_one | 2019-01-06
(1 row)
db_replica=# select * from t1_p2020;
sno | emp_id | date_of_join
-----+---------+--------------
2 | emp_two | 2020-01-06
(1 row)
Questa è una semplice tecnica di partizionamento, ma ciascuna delle suddette semplici partizioni può essere ulteriormente suddivisa in sottopartizioni. Si prega di controllare la documentazione ufficiale di pg_partman pubblicata qui, per ulteriori caratteristiche e funzioni che offre.
Conclusione
La seconda parte di questo blog discuterà di altre estensioni PostgreSQL come pgAudit, pg_repack e HypoPG.