PostgreSQL 17 trae SPLIT PARTITION/MERGE PARTITIONS

PostgreSQL como base de datos está en constante evolución y en cada versión se ven varias nuevas funcionalidades, y el grupo de desarrollo va informando las funcionalidades y en avance en el commitfest y acorde con este hilo de discusión , se va a permitir los comandos SPLIT/MERGE para manejar las particiones de una tabla particionada, acorde a la documentación hasta la fecha estos comandos permiten lo siguiente:

  • SPLIT: permite separar una partición en otras más, definidendo en las otras los nuevos rangos o listas de valores
  • MERGE: permite unir varias particiones en una, definidendo en la nueva el nuevos rango o lista de valores.

    Nota: Ninguna de las dos está permitida sobre tablas particionadas en modo HASH y pueden generar algunos bloqueos, por lo que se recomienda aplicarlos en momentos de poca o ninguna carga de trabajo en la base de datos

Un ejemplo del uso de esta nueva funcionalidad se muestra a continuación.

 postgres=# select version();
                                                 version                                                  
----------------------------------------------------------------------------------------------------------
 PostgreSQL 17devel on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, 64-bit
(1 row)
-- TABLE PARTITION DEFINITION
postgres=# CREATE TABLE medidas (
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);

CREATE TABLE medidas_y2006m02 PARTITION OF medidas
    FOR VALUES FROM ('2006-02-01') TO ('2006-03-01');

CREATE TABLE medidas_y2006m03 PARTITION OF medidas
    FOR VALUES FROM ('2006-03-01') TO ('2006-04-01');

CREATE TABLE medidas_y2006m04 PARTITION OF medidas
    FOR VALUES FROM ('2006-04-01') TO ('2006-05-01');    
    
INSERT INTO medidas SELECT i, '2006-02-01'::date +i, i, i from generate_series (1,80) as i;
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
INSERT 0 80
postgres=# \d+ medidas
                                    Partitioned table "public.medidas"
  Column   |  Type   | Collation | Nullable | Default | Storage | Compression | Stats target | Description 
-----------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
 city_id   | integer |           | not null |         | plain   |             |              | 
 logdate   | date    |           | not null |         | plain   |             |              | 
 peaktemp  | integer |           |          |         | plain   |             |              | 
 unitsales | integer |           |          |         | plain   |             |              | 
Partition key: RANGE (logdate)
Not-null constraints:
    "medidas_city_id_not_null" NOT NULL "city_id"
    "medidas_logdate_not_null" NOT NULL "logdate"
Partitions: medidas_y2006m02 FOR VALUES FROM ('2006-02-01') TO ('2006-03-01'),
            medidas_y2006m03 FOR VALUES FROM ('2006-03-01') TO ('2006-04-01'),
            medidas_y2006m04 FOR VALUES FROM ('2006-04-01') TO ('2006-05-01')
 
 
--MERGE
postgres=# ALTER TABLE medidas merge partitions (medidas_y2006m02,medidas_y2006m03) into medidas_y2006m0203;
ALTER TABLE
postgres=# \d+ medidas
                                    Partitioned table "public.medidas"
  Column   |  Type   | Collation | Nullable | Default | Storage | Compression | Stats target | Description 
-----------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
 city_id   | integer |           | not null |         | plain   |             |              | 
 logdate   | date    |           | not null |         | plain   |             |              | 
 peaktemp  | integer |           |          |         | plain   |             |              | 
 unitsales | integer |           |          |         | plain   |             |              | 
Partition key: RANGE (logdate)
Not-null constraints:
    "medidas_city_id_not_null" NOT NULL "city_id"
    "medidas_logdate_not_null" NOT NULL "logdate"
Partitions: medidas_y2006m0203 FOR VALUES FROM ('2006-02-01') TO ('2006-04-01'),
            medidas_y2006m04 FOR VALUES FROM ('2006-04-01') TO ('2006-05-01')

postgres=# ALTER TABLE medidas SPLIT PARTITION medidas_y2006m04 INTO
    (PARTITION medidas_y2006m04_01 FOR VALUES FROM ('2006-04-01') TO ('2006-04-15'),
     PARTITION medidas_y2006m04_02 FOR VALUES FROM ('2006-04-15') TO ('2006-05-01')); 
ALTER TABLE
postgres=# \d+ medidas
                                    Partitioned table "public.medidas"
  Column   |  Type   | Collation | Nullable | Default | Storage | Compression | Stats target | Description 
-----------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
 city_id   | integer |           | not null |         | plain   |             |              | 
 logdate   | date    |           | not null |         | plain   |             |              | 
 peaktemp  | integer |           |          |         | plain   |             |              | 
 unitsales | integer |           |          |         | plain   |             |              | 
Partition key: RANGE (logdate)
Not-null constraints:
    "medidas_city_id_not_null" NOT NULL "city_id"
    "medidas_logdate_not_null" NOT NULL "logdate"
Partitions: medidas_y2006m0203 FOR VALUES FROM ('2006-02-01') TO ('2006-04-01'),
            medidas_y2006m04_01 FOR VALUES FROM ('2006-04-01') TO ('2006-04-15'),
            medidas_y2006m04_02 FOR VALUES FROM ('2006-04-15') TO ('2006-05-01')
 
 
--SPLIT
postgres=# ALTER TABLE medidas SPLIT PARTITION medidas_y2006m04 INTO
    (PARTITION medidas_y2006m04_01 FOR VALUES FROM ('2006-04-01') TO ('2006-04-15'),
     PARTITION medidas_y2006m04_02 FOR VALUES FROM ('2006-04-15') TO ('2006-05-01')); 
ALTER TABLE
postgres=# \d+ medidas
                                    Partitioned table "public.medidas"
  Column   |  Type   | Collation | Nullable | Default | Storage | Compression | Stats target | Description 
-----------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
 city_id   | integer |           | not null |         | plain   |             |              | 
 logdate   | date    |           | not null |         | plain   |             |              | 
 peaktemp  | integer |           |          |         | plain   |             |              | 
 unitsales | integer |           |          |         | plain   |             |              | 
Partition key: RANGE (logdate)
Not-null constraints:
    "medidas_city_id_not_null" NOT NULL "city_id"
    "medidas_logdate_not_null" NOT NULL "logdate"
Partitions: medidas_y2006m0203 FOR VALUES FROM ('2006-02-01') TO ('2006-04-01'),
            medidas_y2006m04_01 FOR VALUES FROM ('2006-04-01') TO ('2006-04-15'),
            medidas_y2006m04_02 FOR VALUES FROM ('2006-04-15') TO ('2006-05-01')
 

Hacer esta actividad antes de la versión 17 era posible juntando varios comandos de ATTACH PARTITION y DETACH PARTITION, además de pasar los datos correspondientes de un lugar a otro acorde a las restricciones de rango o lista, lo cual puede ser complicado y tedioso.
Ahora en esta nueva versión 17 esto puede ser más sencillo, lo cual demuestra una vez más como PostgreSQL va evolucionando y agregando siempre nuevas funcionalidades para hacer más fácil en trabajo y estar acorde a las necesidades, haciéndolo a su vez más competitiva dicho motor de base de datos. Entonces a esperar hasta finales de este año (2024) para comenzar a disfrutar de estas opciones

Deja un comentario