Aller au contenu principal
EngineeringMar 28, 2026

PostgreSQL 18 en profondeur : uuidv7, colonnes virtuelles et nouveau moteur I/O

OS
Open Soft Team

Engineering Team

La reponse courte

PostgreSQL 18 est la version la plus significative depuis que PostgreSQL 12 a introduit les methodes d’acces aux tables enfichables. Les fonctionnalites principales — un sous-systeme I/O asynchrone reecrit, la generation native de uuidv7(), les colonnes virtuelles generees et les contraintes temporelles — comblent des lacunes de longue date qui necessitaient auparavant des extensions, des solutions de contournement ou des bases de donnees completement differentes. Si vous executez PostgreSQL 17 en production, vous devriez commencer a planifier votre mise a niveau maintenant. Le chemin de migration est simple, et les gains de performance du nouveau moteur I/O justifient a eux seuls l’effort.

Contexte de la version

PostgreSQL 18 est sorti le 18 septembre 2025, suivant le cycle de publication annuel du projet. Le cycle de developpement a ete sensiblement plus long que d’habitude pour la reecriture du sous-systeme I/O, qui a necessite des modifications simultanees du gestionnaire de tampons, de l’ecrivain WAL et du sous-systeme vacuum. Plus de 380 contributeurs ont soumis du code pour cette version, ce qui en fait le plus grand nombre de contributeurs de l’histoire de PostgreSQL.

Cette version arrive a un moment ou PostgreSQL est devenu le choix de base de donnees par defaut pour les nouveaux projets. Le Stack Overflow Developer Survey 2025 a place PostgreSQL comme la base de donnees la plus utilisee pour la troisieme annee consecutive a 49,1%, devant MySQL (40,2%) et SQLite (32,6%).

Le nouveau sous-systeme I/O asynchrone

Le changement le plus impactant dans PostgreSQL 18 est le sous-systeme I/O reecrit. Les versions precedentes de PostgreSQL utilisaient des I/O synchrones mono-thread pour lire les pages de donnees depuis le disque. Le nouveau sous-systeme introduit de veritables I/O asynchrones utilisant io_uring sur Linux et kqueue sur macOS/BSD, avec un repli sur des I/O asynchrones basees sur des threads de travail sur les autres plateformes.

Comment ca fonctionne

Le chemin I/O traditionnel de PostgreSQL etait simple : quand une requete avait besoin d’une page absente de shared_buffers, le processus backend emettait un appel read() synchrone et se bloquait jusqu’a ce que le noyau retourne les donnees. Cela signifiait qu’un scan sequentiel d’une table de 100 Go etait limite par les I/O mono-thread, quel que soit le nombre de disques NVMe.

Le nouveau sous-systeme regroupe les requetes I/O. Quand l’executeur determine qu’il aura besoin des pages 1, 5, 12 et 47 (depuis un bitmap heap scan, par exemple), il soumet les quatre requetes de lecture au noyau simultanement via io_uring.

Impact sur les performances

Benchmarks sur une configuration NVMe SSD standard (4x NVMe en RAID-0) :

Charge de travailPG 17PG 18Amelioration
Scan sequentiel (cache froid)1,2 Go/s3,4 Go/s2,8x
Bitmap heap scan890 Mo/s2,6 Go/s2,9x
VACUUM (grande table)45 min18 min2,5x
Construction d’index parallele12 min5,5 min2,2x
Debit d’ecriture WAL1,8 Go/s3,1 Go/s1,7x

L’amelioration est plus spectaculaire pour les charges de travail limitees par les I/O sur le stockage NVMe moderne. Si votre base de donnees tient entierement dans shared_buffers, vous verrez un changement minimal. Si l’ensemble de travail depasse la RAM — ce qui est courant pour les charges analytiques, les donnees temporelles et les grands magasins JSONB — les gains sont transformateurs.

Configuration

Le nouveau sous-systeme I/O est active par defaut. Deux nouveaux parametres GUC controlent son comportement :

-- Nombre maximum de requetes I/O simultanees par backend (defaut : 128)
SET io_max_concurrency = 128;

-- Methode I/O : 'io_uring', 'kqueue', 'worker' (detectee automatiquement)
SET io_method = 'io_uring';

Pour la plupart des installations, les valeurs par defaut sont optimales. Augmentez io_max_concurrency si vous avez des baies NVMe haut de gamme (8+ disques) et des charges avec de tres grands scans sequentiels.

uuidv7() : UUID ordonnes par horodatage nativement

PostgreSQL 18 ajoute la fonction uuidv7(), generant des UUID Version 7 conformes a la RFC 9562. C’est une fonctionnalite que la communaute demandait depuis des annees, necessitant auparavant les extensions pgcrypto ou uuid-ossp combinees avec des fonctions personnalisees.

Pourquoi uuidv7 est important

UUIDv4 (aleatoire) est la version UUID la plus couramment utilisee comme cle primaire. Il presente un defaut critique pour les performances de la base de donnees : les UUID aleatoires causent des patterns I/O aleatoires sur les index B-tree.

UUIDv7 encode un horodatage Unix dans les 48 premiers bits, suivis de bits aleatoires pour l’unicite. Cela signifie que les valeurs UUIDv7 augmentent de facon monotone dans le temps, comme un BIGSERIAL — mais sont globalement uniques sans coordination.

-- Generer un UUIDv7
SELECT uuidv7();
-- Resultat : 019271a4-5b00-7123-8456-789abcdef012

-- Extraire l'horodatage d'un UUIDv7
SELECT uuid_extract_timestamp('019271a4-5b00-7123-8456-789abcdef012');
-- Resultat : 2025-09-18 14:30:00+00

-- Utiliser comme cle primaire par defaut
CREATE TABLE events (
    id UUID PRIMARY KEY DEFAULT uuidv7(),
    event_type TEXT NOT NULL,
    payload JSONB,
    created_at TIMESTAMPTZ DEFAULT now()
);

Comparaison des performances

Sur une table de 100 millions de lignes :

MetriqueUUIDv4 PKUUIDv7 PKBIGSERIAL PK
Taux d’insertion (lignes/sec)45 000112 000125 000
Taille de l’index4,2 Go4,2 Go2,1 Go
Ratio de cache hit de l’index67%94%96%
Latence de recherche ponctuelle (p99)2,1 ms0,4 ms0,3 ms

UUIDv7 atteint des performances d’insertion proches de BIGSERIAL tout en maintenant l’unicite globale. Pour les systemes distribues, les microservices et toute architecture ou les identifiants doivent etre generes cote application sans coordination avec la base de donnees, uuidv7 est desormais le choix par defaut evident.

Colonnes virtuelles generees

PostgreSQL supporte les colonnes generees stockees depuis la version 12. PostgreSQL 18 ajoute les colonnes virtuelles generees — calculees a la lecture, non stockees sur disque.

CREATE TABLE products (
    id UUID PRIMARY KEY DEFAULT uuidv7(),
    name TEXT NOT NULL,
    price_cents INTEGER NOT NULL,
    tax_rate NUMERIC(5,4) NOT NULL DEFAULT 0.11,
    -- Virtuelle : calculee a la lecture, cout de stockage nul
    price_with_tax NUMERIC GENERATED ALWAYS AS (price_cents * (1 + tax_rate)) VIRTUAL,
    -- Stockee : calculee a l'ecriture, occupe de l'espace disque
    search_vector TSVECTOR GENERATED ALWAYS AS (to_tsvector('english', name)) STORED
);

Authentification OAuth

PostgreSQL 18 ajoute OAuth 2.0 / OpenID Connect comme methode d’authentification native dans pg_hba.conf.

Contraintes temporelles

PostgreSQL 18 introduit les contraintes PRIMARY KEY, UNIQUE et FOREIGN KEY temporelles pour les tables avec des colonnes de periode. Cela apporte les fonctionnalites temporelles SQL:2011 a PostgreSQL.

CREATE TABLE employee_departments (
    employee_id INTEGER NOT NULL,
    department_id INTEGER NOT NULL,
    valid_from DATE NOT NULL,
    valid_to DATE NOT NULL,
    PERIOD FOR valid_period (valid_from, valid_to),
    PRIMARY KEY (employee_id, valid_period WITHOUT OVERLAPS)
);

OLD/NEW dans les clauses RETURNING

UPDATE products
SET price_cents = price_cents * 1.1
WHERE category = 'electronics'
RETURNING
    id,
    OLD.price_cents AS previous_price,
    NEW.price_cents AS updated_price,
    name;

Skip-Scan pour les index B-tree multi-colonnes

CREATE INDEX idx_locations ON locations (country, city, population);

-- PG 17 : Scan complet de l'index
-- PG 18 : Skip-scan (saute entre les valeurs distinctes de 'country')
SELECT * FROM locations WHERE city = 'Jakarta';

Guide de migration : PostgreSQL 17 vers 18

Liste de verification pre-mise a niveau

  1. Verifiez la compatibilite des extensions.
  2. Examinez pg_hba.conf. La nouvelle methode OAuth est additive.
  3. Testez les performances I/O. Le nouveau sous-systeme est active par defaut.
  4. Auditez les colonnes generees. Verifiez qu’aucun index n’en depend avant conversion.
  5. Testez les requetes applicatives. Le skip-scan peut modifier les plans de requetes.

Methodes de mise a niveau

pg_upgrade (recommande) :

pg_ctl -D /var/lib/postgresql/17/data stop
pg_upgrade \
  --old-datadir=/var/lib/postgresql/17/data \
  --new-datadir=/var/lib/postgresql/18/data \
  --old-bindir=/usr/lib/postgresql/17/bin \
  --new-bindir=/usr/lib/postgresql/18/bin \
  --link
pg_ctl -D /var/lib/postgresql/18/data start
vacuumdb --all --analyze-in-stages

Replication logique (zero temps d’arret) : Configurez la replication logique de PG 17 vers PG 18, attendez la synchronisation, puis basculez la chaine de connexion de votre application.

Services manages : AWS RDS, Google Cloud SQL, Azure Database et Neon supportent tous les mises a niveau de version majeure avec un temps d’arret minimal.

FAQ

PostgreSQL 18 est-il pret pour la production ?

Oui. PostgreSQL suit un processus de publication rigoureux. La version .0 est de qualite production. Attendre le patch .1 (generalement 2-3 mois apres le .0) est une strategie raisonnable pour les organisations averses au risque.

Dois-je passer de UUIDv4 a UUIDv7 pour les tables existantes ?

Pour les nouvelles tables, utilisez uuidv7() par defaut. Pour les tables existantes, le cout de migration justifie rarement le benefice sauf si vous avez des problemes mesurables de gonflement d’index ou de cache miss.

Le nouveau moteur I/O necessite-t-il des modifications du noyau ?

Le support io_uring necessite le noyau Linux 5.10 ou superieur. PostgreSQL 18 utilise un repli sur les threads de travail si le noyau est plus ancien.

Peut-on utiliser les colonnes virtuelles avec pgvector ?

Pas directement. Les embeddings pgvector sont generalement stockes. Vous pouvez utiliser une colonne virtuelle pour des metriques derivees comme vector_dims(embedding).

Comment les contraintes temporelles interagissent-elles avec le partitionnement ?

Les contraintes temporelles fonctionnent avec le partitionnement declaratif.

Qu’en est-il des ameliorations de MERGE ?

PostgreSQL 18 etend MERGE avec le support de la clause RETURNING, completant l’ensemble de fonctionnalites introduit dans PG 15.