Esta es la continuación de mi entrada de blog anterior en la que toqué un tema de las extensiones de PostgreSQL. Las extensiones de PostgreSQL son un conjunto de mejoras plug and play que agregan un conjunto de características adicionales a un clúster de PostgreSQL. Algunas de estas funciones son tan simples como leer o escribir en una base de datos externa, mientras que otras podrían ser una solución sofisticada para implementar la replicación de la base de datos, el monitoreo, etc.
PostgreSQL ha evolucionado a lo largo de los años desde un simple ORDBMS de código abierto hasta un poderoso sistema de base de datos con más de 30 años de desarrollo activo que ofrece confiabilidad, rendimiento y todas las características compatibles con ACID. Con el lanzamiento de PostgreSQL 12 hace unos meses, este software de base de datos se está volviendo más grande, mejor y más rápido.
Ocasionalmente, era necesario agregar extensiones a un clúster de PostgreSQL para lograr una funcionalidad mejorada que no estaba disponible en el código nativo, porque no se desarrollaron debido a limitaciones de tiempo o debido a la evidencia insuficiente de la base de datos de casos extremos. problemas. Voy a discutir algunas de mis extensiones favoritas sin ningún orden en particular, con algunas demostraciones que usan los desarrolladores y administradores de bases de datos.
Algunas de estas extensiones pueden requerir que se incluyan en el parámetro del servidor shared_preload_libraries como una lista separada por comas para ser precargada al inicio del servidor. Aunque la mayoría de las extensiones están incluidas en el módulo contrib del código fuente, algunas deben descargarse de un sitio web externo dedicado solo a las extensiones de PostgreSQL llamado PostgreSQL Extension Network.
En esta serie de blogs de dos partes, analizaremos las extensiones utilizadas para acceder a datos (postgres_fwd) y reducir o archivar bases de datos (pg_partman). Las extensiones adicionales se discutirán en la segunda parte.
postgres_fdw
postgres_fdw es una extensión contenedora de datos externa que se puede usar para acceder a datos almacenados en servidores PostgreSQL externos. Esta extensión es similar a una extensión anterior llamada dblink, pero difiere de su predecesora al ofrecer una sintaxis compatible con los estándares y un mejor rendimiento.
Los componentes importantes de postgres_fdw son un servidor, un mapeo de usuarios y una tabla foránea. Hay una sobrecarga menor añadida al costo real de ejecutar consultas en servidores remotos, que es la sobrecarga de comunicación. La extensión postgres_fdw también es capaz de comunicarse con un servidor remoto que tenga una versión hasta PostgreSQL 8.3, por lo que es compatible con versiones anteriores.
Demostración
La demostración mostrará una conexión de PostgreSQL 12 a una base de datos PostgreSQL 11. La configuración de pg_hba.conf ya se ha configurado para que los servidores se comuniquen entre sí. Los archivos de control de extensiones deben cargarse en el directorio de inicio compartido de PostgreSQL antes de crear la extensión desde dentro de un clúster de PostgreSQL.
Servidor 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)
Servidor de origen:
$ /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)
La operación ESCRIBIR del servidor de origen refleja la tabla del servidor remoto inmediatamente. También existe una extensión similar llamada oracle_fdw que permite el acceso de LECTURA y ESCRITURA entre las tablas PostgreSQL y Oracle. Además de eso, hay otra extensión llamada file_fdw que permite el acceso a datos desde archivos planos en el disco. Consulte la documentación oficial de postgres_fdw publicada aquí para obtener más información y detalles.
pg_partman
A medida que crecen las bases de datos y las tablas, siempre existe la necesidad de reducir las bases de datos, archivar los datos que no se necesitan o al menos particionar las tablas en varios fragmentos más pequeños. Esto es para que el optimizador de consultas solo visite las partes de la tabla que satisfacen las condiciones de la consulta, en lugar de escanear todo el montón de tablas.
PostgreSQL ha estado ofreciendo funciones de particionamiento durante mucho tiempo, incluidas las técnicas de rango, lista, hash y subparticionamiento. Sin embargo, requiere muchos esfuerzos de administración y gestión, como definir tablas secundarias que heredan las propiedades de una tabla principal para convertirse en sus particiones, crear funciones de activación para redirigir los datos a una partición y crear además activadores para llamar a esas funciones, etc. Esto es donde pg_partman entra en juego, donde todas estas molestias se solucionan automáticamente.
Demostración
Mostraré una demostración rápida de cómo configurar las cosas e insertar datos de muestra. Verá cómo los datos insertados en la tabla principal se redireccionan automáticamente a las particiones simplemente configurando pg_partman. Es importante que la columna de clave de partición no sea nula.
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)
Esta es una técnica de partición simple, pero cada una de las particiones simples anteriores se puede dividir en subparticiones. Consulte la documentación oficial de pg_partman publicada aquí para conocer más características y funciones que ofrece.
Conclusión
La segunda parte de este blog discutirá otras extensiones de PostgreSQL como pgAudit, pg_repack e HypoPG.