Dies ist die Fortsetzung meines vorherigen Blogeintrags, in dem ich ein Thema der PostgreSQL-Erweiterungen angesprochen hatte. PostgreSQL-Erweiterungen sind ein Plug-and-Play-Satz von Erweiterungen, die einem PostgreSQL-Cluster einen zusätzlichen Funktionssatz hinzufügen. Einige dieser Funktionen sind so einfach wie das Lesen oder Schreiben in eine externe Datenbank, während andere eine ausgeklügelte Lösung zur Implementierung von Datenbankreplikation, Überwachung usw. sein könnten.
PostgreSQL hat sich im Laufe der Jahre von einem einfachen Open-Source-ORDBMS zu einem leistungsstarken Datenbanksystem mit über 30 Jahren aktiver Entwicklung entwickelt, das Zuverlässigkeit, Leistung und alle ACID-konformen Funktionen bietet. Mit PostgreSQL 12, das vor einigen Monaten veröffentlicht wurde, wird diese Datenbanksoftware immer größer, besser und schneller.
Gelegentlich mussten Erweiterungen zu einem PostgreSQL-Cluster hinzugefügt werden, um erweiterte Funktionen zu erreichen, die im nativen Code nicht verfügbar waren, weil sie entweder aus Zeitgründen oder aufgrund unzureichender Beweise für eine Edge-Case-Datenbank nicht entwickelt wurden Probleme. Ich werde einige meiner bevorzugten Erweiterungen in keiner bestimmten Reihenfolge besprechen, mit einigen Demos, die von Entwicklern und DBAs verwendet werden.
Einige dieser Erweiterungen müssen möglicherweise in den Serverparameter shared_preload_libraries als kommagetrennte Liste aufgenommen werden, die beim Serverstart vorab geladen wird. Obwohl die meisten Erweiterungen im contrib-Modul des Quellcodes enthalten sind, müssen einige von einer externen Website heruntergeladen werden, die nur PostgreSQL-Erweiterungen namens PostgreSQL Extension Network gewidmet ist.
In dieser zweiteiligen Blogserie werden wir Erweiterungen besprechen, die verwendet werden, um auf Daten zuzugreifen (postgres_fwd) und Datenbanken zu verkleinern oder zu archivieren (pg_partman). Weitere Erweiterungen werden im zweiten Teil besprochen.
postgres_fdw
postgres_fdw ist eine fremde Daten-Wrapper-Erweiterung, die verwendet werden kann, um auf Daten zuzugreifen, die auf externen PostgreSQL-Servern gespeichert sind. Diese Erweiterung ähnelt einer älteren Erweiterung namens dblink, unterscheidet sich jedoch von ihrem Vorgänger durch eine standardkonforme Syntax und eine bessere Leistung.
Die wichtigen Komponenten von postgres_fdw sind ein Server, eine Benutzerzuordnung und eine Fremdtabelle. Zu den tatsächlichen Kosten für die Ausführung von Abfragen an Remote-Servern kommt ein geringer Overhead hinzu, nämlich der Kommunikations-Overhead. Die postgres_fdw-Erweiterung ist auch in der Lage, mit einem entfernten Server mit einer Version bis zu PostgreSQL 8.3 zu kommunizieren und ist somit abwärtskompatibel mit früheren Versionen.
Demo
Die Demo zeigt eine Verbindung von PostgreSQL 12 zu einer PostgreSQL 11-Datenbank. Die pg_hba.conf-Einstellungen wurden bereits konfiguriert, damit die Server miteinander kommunizieren können. Die Steuerdateien für die Erweiterungen müssen in das gemeinsame PostgreSQL-Basisverzeichnis geladen werden, bevor die Erweiterung innerhalb eines PostgreSQL-Clusters erstellt wird.
Remote-Server:
$ /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)
Quellserver:
$ /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)
Die WRITE-Operation vom Quellserver spiegelt sofort die Remote-Server-Tabelle wider. Es gibt auch eine ähnliche Erweiterung namens oracle_fdw, die den Lese- und Schreibzugriff zwischen PostgreSQL- und Oracle-Tabellen ermöglicht. Darüber hinaus gibt es eine weitere Erweiterung namens file_fdw, die den Datenzugriff von Flatfiles auf der Festplatte ermöglicht. Weitere Informationen und Details finden Sie in der hier veröffentlichten offiziellen Dokumentation von postgres_fdw.
pg_partman
Wenn Datenbanken und Tabellen wachsen, besteht immer die Notwendigkeit, Datenbanken zu verkleinern, nicht benötigte Daten zu archivieren oder zumindest Tabellen in verschiedene kleinere Fragmente zu partitionieren. Auf diese Weise besucht der Abfrageoptimierer nur die Teile der Tabelle, die die Abfragebedingungen erfüllen, anstatt den gesamten Tabellenhaufen zu scannen.
PostgreSQL bietet seit langem Partitionierungsfunktionen an, darunter Range-, List-, Hash- und Subpartitioning-Techniken. Es erfordert jedoch viel Administrations- und Verwaltungsaufwand, z. B. das Definieren von untergeordneten Tabellen, die Eigenschaften einer übergeordneten Tabelle erben, um ihre Partitionen zu werden, das Erstellen von Triggerfunktionen zum Umleiten von Daten in eine Partition und das weitere Erstellen von Triggern zum Aufrufen dieser Funktionen usw. Dies ist wo pg_partman ins Spiel kommt, wobei all diese Probleme automatisch erledigt werden.
Demo
Ich werde eine kurze Demo zeigen, wie Dinge eingerichtet und Beispieldaten eingefügt werden. Sie werden sehen, wie die in die Haupttabelle eingefügten Daten automatisch an die Partitionen umgeleitet werden, indem Sie einfach pg_partman einrichten. Es ist wichtig, dass die Partitionsschlüsselspalte nicht null ist.
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)
Dies ist eine einfache Partitionierungstechnik, aber jede der obigen einfachen Partitionen kann weiter in Unterpartitionen unterteilt werden. Bitte überprüfen Sie die hier veröffentlichte offizielle Dokumentation von pg_partman auf weitere Features und Funktionen, die es bietet.
Fazit
Teil zwei dieses Blogs behandelt andere PostgreSQL-Erweiterungen wie pgAudit, pg_repack und HypoPG.