Crear una tabla particionada por range mensual (generar las particiones en un bucle)
PostgreSQLParticionamientoComando
CREATE TABLE sales (
id bigint GENERATED ALWAYS AS IDENTITY,
created_at date NOT NULL,
customer_id bigint NOT NULL,
amount numeric(12,2),
PRIMARY KEY (id, created_at)
) PARTITION BY RANGE (created_at);
-- An index defined on the parent propagates to all partitions automatically
CREATE INDEX sales_customer_id_idx ON sales (customer_id);
-- 12 monthly partitions for 2026
DO $$
DECLARE
m date;
BEGIN
FOR m IN SELECT generate_series(date '2026-01-01', date '2026-12-01', interval '1 month')::date LOOP
EXECUTE format(
'CREATE TABLE IF NOT EXISTS %I PARTITION OF sales FOR VALUES FROM (%L) TO (%L)',
'sales_' || to_char(m, 'YYYY_MM'), m, (m + interval '1 month')::date);
END LOOP;
END $$;
-- Hierarchy, bounds and sizes
SELECT t.relid::regclass AS partition_name,
t.parentrelid::regclass AS parent,
t.isleaf,
t.level,
pg_get_expr(c.relpartbound, c.oid) AS bounds,
pg_size_pretty(pg_total_relation_size(t.relid)) AS total_size
FROM pg_partition_tree('sales') t
JOIN pg_class c ON c.oid = t.relid
ORDER BY t.level, bounds;Qué hace
Crea un padre particionado por RANGE sobre una columna de fecha, un índice que se propaga a todas las particiones y 12 particiones mensuales en un bucle; después lista la jerarquía con los límites y tamaños.
Cuándo usarlo
Para tablas grandes y en crecimiento continuo que eliminan periódicamente datos antiguos (DETACH/DROP) o cuyas consultas filtran sobre todo por rango de fechas (pedidos, logs, series temporales).
Precaución
En una tabla particionada, las restricciones PRIMARY KEY/UNIQUE deben incluir la clave de partición (no hay índices únicos globales). El límite inferior es inclusivo y el superior exclusivo (FROM inclusivo, TO exclusivo). Sin un job que cree por adelantado las particiones futuras (pg_cron, pg_partman), los INSERT fuera de rango fallan. Miles de particiones aumentan el tiempo de planificación y la sobrecarga de bloqueos. CREATE INDEX CONCURRENTLY no está soportado en el padre: use CREATE INDEX ... ON ONLY en el padre, CREATE INDEX CONCURRENTLY en cada partición y después ALTER INDEX ... ATTACH PARTITION.
Relacionado
- Conectar una tabla preparada como partición con un bloqueo breve (ATTACH PARTITION)
- Desconectar una partición antigua sin bloquear el tráfico activo (DETACH CONCURRENTLY)
- Trampa de la partición default: la nueva partición falla con 'would be violated by some row'
- Verificar que el partition pruning funciona (en tiempo de planificación y de ejecución)
- Automatizar la creación y la retención de particiones con pg_partman