Това е продължение на предишния ми запис в блога, в който засегнах тема за PostgreSQL Extensions. Разширенията на PostgreSQL са Plug and Play набор от подобрения, които добавят допълнителен набор от функции към PostgreSQL клъстер. Някои от тези функции са толкова прости като четене или запис във външна база данни, докато други биха могли да бъдат сложно решение за внедряване на репликация на база данни, наблюдение и т.н.
PostgreSQL се е развил през годините от обикновена ORDBMS с отворен код до мощна система за бази данни с над 30 години активно развитие, предлагаща надеждност, производителност и всички съвместими с ACID функции. С PostgreSQL 12, пуснат преди няколко месеца, този софтуер за база данни става все по-голям, по-добър и по-бърз.
Понякога е трябвало да се добавят разширения към клъстер на PostgreSQL, за да се постигне подобрена функционалност, която не е била достъпна в собствения код, тъй като или не са разработени поради ограничения във времето или поради недостатъчни доказателства в базата данни за крайни случаи проблеми. Ще обсъдя няколко от любимите си разширения без определен ред, с някои демонстрации, които се използват от разработчици и администратори на данни.
Някои от тези разширения може да изискват да бъдат включени в сървърния параметър shared_preload_libraries като списък, разделен със запетая, който да бъде предварително зареден при стартиране на сървъра. Въпреки че повечето от разширенията са включени в модула contrib на изходния код, някои трябва да бъдат изтеглени от външен уебсайт, посветен само на разширенията на PostgreSQL, наречен PostgreSQL Extension Network.
В тази серия от блогове от две части ще обсъдим разширенията, използвани за достъп до данни (postgres_fwd) и свиване или архивиране на бази данни (pg_partman). Допълнителните разширения ще бъдат обсъдени във втората част.
postgres_fdw
postgres_fdw е разширение за обвивка на чужди данни, което може да се използва за достъп до данни, съхранявани във външни PostgreSQL сървъри. Това разширение е подобно на по-старо разширение, наречено dblink, но се различава от предшественика си, като предлага съвместим със стандартите синтаксис и по-добра производителност.
Важните компоненти на postgres_fdw са сървър, потребителско картографиране и чужда таблица. Към действителните разходи за изпълнение на заявки към отдалечени сървъри се добавят незначителни допълнителни разходи, които са комуникационните разходи. Разширението postgres_fdw също така може да комуникира с отдалечен сървър с версия чак до PostgreSQL 8.3, като по този начин е обратно съвместима с по-ранни версии.
Демо
Демото ще покаже връзка от PostgreSQL 12 към база данни на PostgreSQL 11. Настройките на pg_hba.conf вече са конфигурирани за сървърите да разговарят помежду си. Контролните файлове на разширенията трябва да бъдат заредени в споделената домашна директория на PostgreSQL, преди да създадете разширението от вътрешността на PostgreSQL клъстер.
Отдалечен сървър:
$ /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)
Изходен сървър:
$ /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)
Операцията WRITE от изходния сървър отразява незабавно таблицата на отдалечения сървър. Също така съществува подобно разширение, наречено oracle_fdw, което позволява достъп за ЧЕТЕНЕ и ЗАПИС между PostgreSQL и Oracle таблици. В допълнение към това има друго разширение, наречено file_fdw, което позволява достъп до данни от плоски файлове на диска. Моля, вижте официалната документация на postgres_fdw, публикувана тук, за повече информация и подробности.
pg_partman
С нарастването на базите данни и таблиците винаги има нужда от свиване на бази данни, архивиране на данни, които не са необходими, или поне разделяне на таблици на различни по-малки фрагменти. Това е така, че оптимизаторът на заявки посещава само частите от таблицата, които отговарят на условията на заявка, вместо да сканира цялата купчина таблици.
PostgreSQL предлага функции за разделяне от дълго време, включително техники за диапазон, списък, хеш и подразделяне. Това обаче изисква много усилия за администриране и управление, като например дефиниране на дъщерни таблици, които наследяват свойствата на родителска таблица, за да станат нейни дялове, създаване на тригерни функции за пренасочване на данни в дял и допълнително създаване на тригери за извикване на тези функции и т.н. където pg_partman влиза в игра, при което всички тези проблеми се поемат автоматично.
Демо
Ще покажа бърза демонстрация на настройка на нещата и вмъкване на примерни данни. Ще видите как данните, вмъкнати в основната таблица, се пренасочват автоматично към дяловете, като просто настроите pg_partman. Важно е колоната с ключ на дяла да не е нула.
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)
Това е проста техника за разделяне, но всеки от горните прости дялове може да бъде допълнително разделен на подраздели. Моля, проверете официалната документация на pg_partman, публикувана тук, за повече функции и функции, които предлага.
Заключение
Втора част от този блог ще обсъди други разширения на PostgreSQL като pgAudit, pg_repack и HypoPG.