À propos de l’utilisation de PostgreSQL et d’UUID comme clé primaire
(maciejwalkowiak.com)- Les UUID sont souvent utilisés comme clés primaires de tables de base de données
- Ils sont faciles à générer, simples à partager entre systèmes distribués et garantissent l’unicité
- Vu la taille des UUID, on peut se demander si c’est vraiment le bon choix, mais dans bien des cas, on n’a pas la main sur cette décision
- Cet article ne cherche pas à répondre à la question « les UUID sont-ils un bon format pour une clé ? », mais explique comment utiliser efficacement des UUID comme clés primaires dans PostgreSQL
Utiliser PostgreSQL et des UUID comme clé primaire
- Qu’est-ce qu’un UUID ?
- Les UUID sont souvent utilisés comme clés primaires de tables de base de données
- Ils peuvent être facilement partagés entre systèmes distribués et garantissent l’unicité
- Leur taille peut faire douter de leur pertinence, mais on n’a souvent pas d’alternative
Le type de données UUID dans PostgreSQL
-
Stocker un UUID comme chaîne de caractères
- PostgreSQL fournit le type de données
textpour stocker des chaînes - Cependant, le type
textn’est pas adapté au stockage d’UUID - PostgreSQL propose un type dédié,
uuid, pour les UUID - Le type
uuidest un type de données sur 128 bits, qui nécessite 16 octets pour stocker une valeur - Le type
textajoute un surcoût de 1 ou 4 octets
- PostgreSQL fournit le type de données
-
Résultats de l’expérience
- Comparaison de deux tables créées pour le test : l’une en type
text, l’autre en typeuuid - Après insertion de 10,000,000 lignes, comparaison de la taille des tables et des index
- La table utilisant le type
textest 54 % plus volumineuse, et la taille de son index est 85 % plus grande
- Comparaison de deux tables créées pour le test : l’une en type
UUID et index B-Tree
-
Index B-Tree et UUID
- Les UUID aléatoires ne conviennent pas bien aux index B-Tree
- Les index B-Tree fonctionnent bien avec des valeurs ordonnées
- En Java,
UUID.randomUUID()renvoie un UUID v4, c’est-à-dire une valeur pseudo-aléatoire - UUID v7 génère des valeurs ordonnées dans le temps, ce qui le rend adapté aux index B-Tree
-
Utiliser UUID v7
- Pour utiliser UUID v7 en Java, la bibliothèque
java-uuid-generatorest nécessaire - Générer des UUID v7 peut améliorer les performances d’insertion
- Pour utiliser UUID v7 en Java, la bibliothèque
Impact d’UUID v7 sur les performances d’INSERT
- Expérience
- Création d’une table utilisant UUID v7, puis mesure des performances en insérant 10 fois 10,000 lignes
- Les résultats restent un peu aléatoires, mais l’insertion d’UUID v7 est environ 2 fois plus rapide
Pour aller plus loin
- PostgreSQL 17 pourrait prendre en charge UUID v7 nativement
- Informations sur le format UUID v7
- Impact des UUID sur les performances lorsqu’ils servent de clé primaire en base de données
Résumé
-
Le problème de la longueur des UUID
- Même avec des optimisations, les UUID ne sont pas le type le plus optimal pour une clé primaire
- Si vous avez le choix, envisagez d’autres options comme TSID
-
La nécessité d’optimiser
- Si vous prévoyez de grands volumes de données ou un trafic élevé, il faut envisager une optimisation
- Changer une clé primaire est une opération difficile, donc il est important de faire le bon choix dès le départ
-
Remarques
- L’auteur n’est pas un expert PostgreSQL ; il partage simplement ce qu’il a appris
- Si cela vous a été utile, n’hésitez pas à faire un retour en commentaire ou sur Twitter
Le récapitulatif de GN⁺
- Cet article traite des moyens efficaces d’utiliser des UUID comme clés primaires dans PostgreSQL
- Il montre, expérimentation à l’appui, que l’utilisation d’UUID v7 peut améliorer les performances d’insertion
- Une optimisation est nécessaire si l’on s’attend à de grands jeux de données ou à un trafic important
- D’autres options, comme TSID, méritent aussi d’être envisagées
4 commentaires
Est-ce déraisonnable d’espérer un encodage en base62 pour les UUID, plutôt que le format standard (hexadécimal + tirets) ?
uuidv7 est imbattable
uuidv8+ est « divin »
Le plus gros obstacle, c’est que ce n’est pas très convivial pour les humains… J’ai encore besoin de cet aspect dans beaucoup de cas.
Avis Hacker News
Recommande d’utiliser
bigserialcomme clé primaire compatible B-tree, et d’envisager un UUID encodé en chaîne comme option de localisateur d’enregistrement externehashids; cela n’a pas de qualité cryptographique et ce n’est pas familier pour le grand publicbase64ni un alphabet contenant des tiretsLors de la conception d’un schéma de base de données, garder à l’esprit les principes de séparation des préoccupations et d’accord mécanique
Les ID aléatoires typés de Stripe ne sont en réalité pas aléatoires
bigserial+HMACchiffrés en AES et encodés en base58Dans Postgres, les UUID aléatoires ne posent pas de gros problème
serial(4 octets) oubigserial(8 octets), mais à l’échelle de l’ensemble d’une table, ce n’est pas un problème majeurAvant d’opposer
serialvs. UUID aléatoire vs. UUID ordonné dans Postgres, il y a beaucoup d’autres sujets plus importants à traiterA récemment choisi ULID comme PK Postgres, et cet article a beaucoup aidé : https://brandur.org/nanoglyphs/026-ids
Préfère ULID car il est compatible avec le type UUID et intègre un horodatage, ce qui fait qu’un tri par ID revient à un tri chronologique
Ce serait bien d’inclure aussi
int64dans la comparaison afin de mesurer le surcoût des UUID par rapport à l’approche traditionnelleLes performances d’insertion sont une mauvaise façon d’évaluer les performances
Dans SQLite, UUID4 est préféré car il y a moins de risque de collisions dans le cache de pages pendant les verrous transactionnels
Préfère les clés primaires entières auto-incrémentées
Le benchmark du temps d’insertion de UUIDv7 inclut le temps de génération du UUID
Il est peu probable que PostgreSQL 17 inclue la prise en charge de UUIDv7
A commencé à utiliser
python-ulid, et estime que ULID est supérieur à UUIDLe lien vers la norme UUID v7 est obsolète ; se référer plutôt à la RFC 9562 : https://datatracker.ietf.org/doc/html/rfc9562