Dette er i forlængelse af mit tidligere blogindlæg, hvor jeg havde berørt et emne om PostgreSQL -udvidelser. PostgreSQL-udvidelser er et plug and play-sæt af forbedringer, der tilføjer et ekstra funktionssæt til en PostgreSQL-klynge. Nogle af disse funktioner er så enkle som at læse eller skrive til en ekstern database, mens andre kunne være en sofistikeret løsning til implementering af databasereplikering, overvågning osv.
PostgreSQL har i årenes løb udviklet sig fra et simpelt open source ORDBMS til et kraftfuldt databasesystem med over 30 års aktiv udvikling, der tilbyder pålidelighed, ydeevne og alle ACID-kompatible funktioner. Med PostgreSQL 12 udgivet for et par måneder siden bliver denne databasesoftware kun større, bedre og hurtigere.
Indimellem skulle udvidelser føjes til en PostgreSQL-klynge for at opnå forbedret funktionalitet, der ikke var tilgængelig i den oprindelige kode, fordi de enten ikke blev udviklet på grund af tidsbegrænsninger eller på grund af utilstrækkelig dokumentation for edge case-database problemer. Jeg vil diskutere et par af mine yndlingsudvidelser i nogen bestemt rækkefølge, med nogle demoer, der bruges af udviklere og DBA'er.
Nogle af disse udvidelser skal muligvis inkluderes i serverparameteren shared_preload_libraries som en kommasepareret liste for at blive forudindlæst ved serverstarten. Selvom de fleste af udvidelserne er inkluderet i bidragsmodulet til kildekoden, skal nogle downloades fra et eksternt websted, der kun er dedikeret til PostgreSQL-udvidelser kaldet PostgreSQL Extension Network.
I denne todelte blogserie vil vi diskutere udvidelser, der bruges til at få adgang til data (postgres_fwd) og formindske eller arkivere databaser (pg_partman). Yderligere udvidelser vil blive diskuteret i anden del.
postgres_fdw
postgres_fdw er en fremmed dataindpakningsudvidelse, der kan bruges til at få adgang til data gemt på eksterne PostgreSQL-servere. Denne udvidelse ligner en ældre udvidelse kaldet dblink, men den adskiller sig fra sin forgænger ved at tilbyde standardkompatibel syntaks og bedre ydeevne.
De vigtige komponenter i postgres_fdw er en server, en brugertilknytning og en fremmed tabel. Der er en mindre overhead tilføjet til de faktiske omkostninger ved at udføre forespørgsler mod fjernservere, hvilket er kommunikationsomkostningerne. Postgres_fdw-udvidelsen er også i stand til at kommunikere med en fjernserver, der har en version helt op til PostgreSQL 8.3, og er således bagudkompatibel med tidligere versioner.
Demo
Demoen vil vise en forbindelse fra PostgreSQL 12 til en PostgreSQL 11-database. Indstillingerne for pg_hba.conf er allerede blevet konfigureret til, at serverne kan tale med hinanden. Extensionskontrolfilerne skal indlæses i PostgreSQL-delte hjemmemappe, før udvidelsen oprettes fra Inde i en PostgreSQL-klynge.
Fjernserver:
$ /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)
Kildeserver:
$ /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)
SKRIV-handlingen fra kildeserveren afspejler den eksterne servertabell med det samme. En lignende udvidelse kaldet oracle_fdw findes også, som muliggør READ- og WRITE-adgang mellem PostgreSQL- og Oracle-tabeller. Ud over det er der en anden udvidelse kaldet file_fdw, som muliggør dataadgang fra flade filer på disken. Se venligst den officielle dokumentation for postgres_fdw offentliggjort her for mere information og detaljer.
pg_partman
Efterhånden som databaser og tabeller vokser, er der altid behov for at formindske databaser, arkivere data, der ikke er nødvendige eller i det mindste opdele tabeller i forskellige mindre fragmenter. Dette er så forespørgselsoptimeringsværktøjet kun besøger de dele af tabellen, der opfylder forespørgselsbetingelserne, i stedet for at scanne hele bunken af tabeller.
PostgreSQL har i lang tid tilbudt partitioneringsfunktioner, herunder Range, List, Hash og Sub-partitioning teknikker. Det kræver dog en masse administrations- og administrationsindsatser, såsom at definere underordnede tabeller, der arver egenskaber fra en overordnet tabel for at blive dens partitioner, oprette triggerfunktioner til at omdirigere data til en partition og yderligere skabe triggere til at kalde disse funktioner osv. Dette er hvor pg_partman kommer i spil, hvor alle disse besvær bliver taget hånd om automatisk.
Demo
Jeg vil vise en hurtig demo af opsætning af ting og indsættelse af eksempeldata. Du vil se, hvordan de data, der er indsat i hovedtabellen, automatisk bliver omdirigeret til partitionerne ved blot at opsætte pg_partman. Det er vigtigt, at partitionsnøglekolonnen ikke er null.
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)
Dette er en simpel partitioneringsteknik, men hver af ovenstående simple partitioner kan yderligere opdeles i underpartitioner. Se venligst den officielle dokumentation for pg_partman, der er offentliggjort her, for flere funktioner og funktioner, den tilbyder.
Konklusion
Del to af denne blog vil diskutere andre PostgreSQL-udvidelser som pgAudit, pg_repack og HypoPG.