Jest to kontynuacja mojego poprzedniego wpisu na blogu, w którym poruszyłem temat rozszerzeń PostgreSQL. Rozszerzenia PostgreSQL to zestaw ulepszeń typu plug and play, które dodają dodatkowy zestaw funkcji do klastra PostgreSQL. Niektóre z tych funkcji są tak proste, jak odczytywanie lub zapisywanie do zewnętrznej bazy danych, podczas gdy inne mogą być wyrafinowanym rozwiązaniem do implementacji replikacji bazy danych, monitorowania itp.
PostgreSQL ewoluował przez lata od prostego ORDBMS typu open source do potężnego systemu bazodanowego z ponad 30-letnim aktywnym rozwojem, oferującego niezawodność, wydajność i wszystkie funkcje zgodne z ACID. Po wydaniu PostgreSQL 12 kilka miesięcy temu to oprogramowanie bazy danych staje się coraz większe, lepsze i szybsze.
Od czasu do czasu rozszerzenia musiały zostać dodane do klastra PostgreSQL, aby osiągnąć ulepszoną funkcjonalność, która była niedostępna w kodzie natywnym, ponieważ nie zostały opracowane z powodu ograniczeń czasowych lub z powodu niewystarczających dowodów na istnienie bazy danych przypadków brzegowych problemy. Zamierzam omówić kilka moich ulubionych rozszerzeń w dowolnej kolejności, z niektórymi wersjami demonstracyjnymi używanymi przez programistów i administratorów baz danych.
Niektóre z tych rozszerzeń mogą wymagać uwzględnienia w parametrze serwera shared_preload_libraries jako listy oddzielonej przecinkami, która zostanie wstępnie załadowana przy uruchomieniu serwera. Chociaż większość rozszerzeń jest zawarta w module contrib w kodzie źródłowym, niektóre należy pobrać z zewnętrznej strony internetowej poświęconej tylko rozszerzeniom PostgreSQL o nazwie PostgreSQL Extension Network.
W tej dwuczęściowej serii blogów omówimy rozszerzenia używane do uzyskiwania dostępu do danych (postgres_fwd) oraz zmniejszania lub archiwizowania baz danych (pg_partman). Dodatkowe rozszerzenia zostaną omówione w drugiej części.
postgres_fdw
postgres_fdw to zewnętrzne rozszerzenie danych, które może być używane do uzyskiwania dostępu do danych przechowywanych na zewnętrznych serwerach PostgreSQL. To rozszerzenie jest podobne do starszego rozszerzenia o nazwie dblink, ale różni się od swojego poprzednika tym, że oferuje zgodną ze standardami składnię i lepszą wydajność.
Ważnymi składnikami postgres_fdw są serwer, mapowanie użytkowników i obca tabela. Do rzeczywistych kosztów wykonywania zapytań na zdalnych serwerach dodawany jest niewielki narzut, jakim jest narzut komunikacyjny. Rozszerzenie postgres_fdw może również komunikować się ze zdalnym serwerem w wersji aż do PostgreSQL 8.3, dzięki czemu jest wstecznie kompatybilne z wcześniejszymi wersjami.
Demo
Demo zaprezentuje połączenie PostgreSQL 12 z bazą danych PostgreSQL 11. Ustawienia pg_hba.conf zostały już skonfigurowane, aby serwery mogły się ze sobą komunikować. Pliki kontrolne rozszerzeń należy załadować do współdzielonego katalogu domowego PostgreSQL przed utworzeniem rozszerzenia z poziomu klastra PostgreSQL.
Serwer zdalny:
$ /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)
Serwer źródłowy:
$ /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)
Operacja WRITE z serwera źródłowego natychmiast odzwierciedla tabelę serwera zdalnego. Istnieje również podobne rozszerzenie o nazwie oracle_fdw, które umożliwia dostęp do odczytu i zapisu między tabelami PostgreSQL i Oracle. Oprócz tego istnieje inne rozszerzenie o nazwie file_fdw, które umożliwia dostęp do danych z plików płaskich na dysku. Aby uzyskać więcej informacji i szczegółów, zapoznaj się z oficjalną dokumentacją postgres_fdw opublikowaną tutaj.
pg_partman
W miarę wzrostu baz danych i tabel zawsze istnieje potrzeba zmniejszania baz danych, archiwizowania danych, które nie są potrzebne lub przynajmniej podziału tabel na różne mniejsze fragmenty. Dzieje się tak dlatego, że optymalizator zapytań odwiedza tylko te części tabeli, które spełniają warunki zapytania, zamiast skanować całą stertę tabel.
PostgreSQL od dawna oferuje funkcje partycjonowania, w tym techniki Range, List, Hash i Sub-partycjonowanie. Wymaga to jednak wielu działań administracyjnych i zarządczych, takich jak definiowanie tabel podrzędnych, które dziedziczą właściwości tabeli nadrzędnej, aby stać się jej partycjami, tworzenie funkcji wyzwalaczy do przekierowywania danych do partycji i dalsze tworzenie wyzwalaczy do wywoływania tych funkcji itp. gdzie w grę wchodzi pg_partman, w którym wszystkie te problemy są rozwiązywane automatycznie.
Demo
Pokażę krótką prezentację konfiguracji i wstawiania przykładowych danych. Zobaczysz, jak dane wstawione do głównej tabeli są automatycznie przekierowywane na partycje, po prostu ustawiając pg_partman. Ważne jest, aby kolumna klucza partycji nie była pusta.
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)
Jest to prosta technika partycjonowania, ale każda z powyższych prostych partycji może być dalej podzielona na podpartycje. Sprawdź oficjalną dokumentację pg_partman opublikowaną tutaj, aby uzyskać więcej funkcji i funkcji, które oferuje.
Wnioski
Część druga tego bloga omówi inne rozszerzenia PostgreSQL, takie jak pgAudit, pg_repack i HypoPG.