Créer une table partitionnée par range mensuel (générer les partitions dans une boucle)
PostgreSQLPartitionnementCommande
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;Ce que fait la commande
Crée un parent partitionné par RANGE sur une colonne de date, un index qui se propage à chaque partition, et 12 partitions mensuelles dans une boucle ; puis liste la hiérarchie avec les bornes et les tailles.
Quand l'utiliser
Pour les grandes tables en croissance continue qui suppriment périodiquement les anciennes données (DETACH/DROP) ou dont les requêtes filtrent surtout par plage de dates (commandes, journaux, séries temporelles).
Attention
Sur une table partitionnée, les contraintes PRIMARY KEY/UNIQUE doivent inclure la clé de partitionnement (il n'existe pas d'index unique global). La borne inférieure est incluse, la borne supérieure exclue (FROM inclus, TO exclu). Sans job qui crée à l'avance les partitions futures (pg_cron, pg_partman), les INSERT hors plage échouent. Des milliers de partitions augmentent le temps de planification et la surcharge des verrous. CREATE INDEX CONCURRENTLY n'est pas pris en charge sur le parent : utilisez CREATE INDEX ... ON ONLY sur le parent, CREATE INDEX CONCURRENTLY sur chaque partition, puis ALTER INDEX ... ATTACH PARTITION.
Voir aussi
- Attacher une table préparée comme partition avec un verrou court (ATTACH PARTITION)
- Détacher une ancienne partition sans bloquer le trafic (DETACH CONCURRENTLY)
- Piège de la partition par défaut : une nouvelle partition échoue avec 'would be violated by some row'
- Vérifier que le partition pruning fonctionne (à la planification et à l'exécution)
- Automatiser la création et la rétention des partitions avec pg_partman