17 sept. 2025·8 min de lecture

UUID vs bigint dans PostgreSQL : choisir des IDs qui tiennent la charge

UUID vs bigint dans PostgreSQL : comparez taille des index, ordre de tri, préparation au sharding, et comment les IDs transitent dans les APIs, le web et le mobile.

UUID vs bigint dans PostgreSQL : choisir des IDs qui tiennent la charge

Pourquoi le choix des identifiants compte plus qu'il n'y paraît

Chaque ligne d'une table PostgreSQL a besoin d'un moyen stable pour être retrouvée. C'est ce que fait un identifiant : il identifie de façon unique un enregistrement, il est généralement la clé primaire et sert de lien pour les relations. D'autres tables le stockent comme clé étrangère, les requêtes font des jointures dessus, et les applications le transmettent comme le « client », « facture » ou « ticket » en question.

Parce que les IDs se retrouvent partout, le choix n'est pas qu'un détail de base de données. Il impacte ensuite la taille des index, les schémas d'écriture, la vitesse des requêtes, les taux de cache, et même des aspects produit comme l'analytics, les imports et le debug. Il influe aussi sur ce que vous exposez dans les URLs et les APIs, et sur la facilité pour une application mobile de stocker et synchroniser des données en toute sécurité.

La plupart des équipes finissent par comparer UUID vs bigint dans PostgreSQL. En termes simples, vous choisissez entre :

  • bigint : un nombre 64 bits, souvent généré par une séquence (1, 2, 3...).
  • UUID : un identifiant 128 bits, d'apparence aléatoire, ou généré de façon ordonnée dans le temps.

Aucune option ne gagne dans tous les cas. Le bigint est compact et favorable aux index et au tri. Les UUID conviennent mieux quand vous avez besoin d'IDs globalement uniques entre systèmes, d'IDs publics plus sûrs, ou si vous attendez des créations de données en de nombreux endroits (services multiples, mobile hors‑ligne, ou sharding futur).

Une règle pratique : décidez en fonction de la façon dont vos données seront créées et partagées, pas seulement de la façon dont elles seront stockées aujourd'hui.

Principes de base : bigint et UUID en clair

Quand on compare UUID vs bigint dans PostgreSQL, on choisit entre deux façons de nommer les lignes : un petit nombre type compteur, ou une valeur plus longue et globalement unique.

Un bigint est un entier 64 bits. Dans PostgreSQL on le génère généralement avec une colonne identity (ou l'ancien motif serial). La base gère une séquence en arrière‑plan et fournit le numéro suivant à chaque insertion. Les IDs ont donc tendance à être 1, 2, 3, 4... C'est simple, lisible et pratique dans les outils et rapports.

Un UUID (Universally Unique Identifier) fait 128 bits. On le voit souvent écrit en 36 caractères avec des tirets, comme 550e8400-e29b-41d4-a716-446655440000. Types courants :

  • v4 : UUID aléatoires. Faciles à générer n'importe où, mais ils ne s'ordonnent pas selon la création.
  • v7 : UUID ordonnés dans le temps. Toujours uniques, mais conçus pour augmenter approximativement avec le temps.

Le stockage est l'une des premières différences pratiques : bigint utilise 8 octets, tandis que UUID utilise 16 octets. Cet écart de taille apparaît dans les index et peut affecter les taux de cache (la base peut contenir moins d'entrées d'index en mémoire).

Pensez aussi à l'endroit où les IDs apparaissent hors de la base. Les bigint tiennent peu de place dans une URL et sont faciles à lire dans les logs. Les UUID sont plus longs et pénibles à taper, mais plus difficiles à deviner et peuvent être générés côté client quand c'est nécessaire.

Taille des index et bloat des tables : ce qui change

La plus grande différence pratique entre bigint et UUID est la taille. Bigint = 8 octets ; UUID = 16 octets. Ça paraît peu jusqu'à ce que vous vous rappeliez que les index répètent vos IDs de nombreuses fois.

L'index de la clé primaire doit rester « chaud » en mémoire pour être rapide. Un index plus petit signifie qu'une plus grande partie tient dans shared_buffers et le cache CPU, donc les recherches et jointures nécessitent moins de lectures disque. Avec des clés UUID, l'index est généralement sensiblement plus volumineux pour un même nombre de lignes.

Le multiplicateur vient des index secondaires. Dans les index B-tree de PostgreSQL, chaque entrée d'index secondaire stocke aussi la valeur de la clé primaire (pour retrouver la ligne). Donc des IDs plus larges gonflent non seulement l'index primaire, mais aussi tous les autres index que vous ajoutez. Si vous avez trois index secondaires, les 8 octets supplémentaires des UUID se retrouvent effectivement à quatre endroits.

Les clés étrangères et les tables de jointure en subissent aussi les conséquences. Toute table référant votre ID le stocke dans ses propres lignes et index. Une table de jointure many-to-many peut être essentiellement deux clés étrangères plus un peu d'overhead, donc doubler la largeur des clés peut changer fortement son empreinte.

En pratique :

  • Les UUID rendent généralement les index primaires et secondaires plus grands, et la différence se cumule quand vous ajoutez des index.
  • Des index plus larges augmentent la pression mémoire et les lectures de pages sous charge.
  • Plus il y a de tables qui référencent la clé (événements, logs, tables de jointure), plus la différence de taille compte.

Si un ID utilisateur apparaît dans users, orders, order_items et un audit_log, cette même valeur est stockée et indexée dans toutes ces tables. Choisir une clé plus large est autant une décision de stockage qu'une décision d'ID.

Ordre de tri et schéma d'écriture : séquentiel vs aléatoire

La plupart des clés primaires PostgreSQL reposent sur un index B-tree. Un B-tree fonctionne mieux quand les nouvelles lignes arrivent près de la fin de l'index, car la base peut append sans beaucoup de réarrangement.

IDs séquentiels : prévisibles et amicaux pour le stockage

Avec une colonne bigint issue d'une identity ou d'une séquence, les nouveaux IDs augmentent dans le temps. Les insertions touchent généralement la partie la plus à droite de l'index, les pages restent pleines, le cache reste chaud, et PostgreSQL fait moins de travail supplémentaire.

Cela compte même si vous n'exécutez jamais ORDER BY id. Le chemin d'écriture doit malgré tout placer chaque nouvelle clé dans l'index dans l'ordre trié.

UUIDs aléatoires : plus de dispersion, plus de churn

Un UUID aléatoire (typique des v4) disperse les insertions dans tout l'index. Cela augmente les risques de page splits, où PostgreSQL doit allouer de nouvelles pages d'index et déplacer des entrées pour faire de la place. Le résultat : plus d'amplification d'écriture — plus d'octets d'index écrits, plus de WAL généré, et souvent plus de travail en arrière‑plan (vacuum et gestion du bloat).

Les UUID ordonnés dans le temps changent la donne. Des UUID qui augmentent majoritairement avec le temps (comme le style UUIDv7 ou d'autres schémas basés sur le temps) restaurent une bonne partie de la localité, tout en restant des UUID de 16 octets et en ayant l'apparence d'UUID dans votre API.

Vous ressentirez ces différences surtout quand vous avez des taux d'insertion élevés, de grandes tables qui ne tiennent pas en mémoire, et plusieurs index secondaires. Si vous êtes sensible aux pics de latence liés aux page splits, évitez les IDs complètement aléatoires sur des tables chaudes en écriture.

Exemple : une table d'événements très sollicitée recevant des logs d'app mobiles toute la journée fonctionnera généralement mieux avec des clés séquentielles ou des UUID ordonnés dans le temps qu'avec des UUID entièrement aléatoires.

Impact sur les performances perceptible

Décidez vite de votre stratégie d'identifiants
Modélisez votre schéma PostgreSQL et testez les choix bigint vs UUID dans une vraie application.
Essayer AppMaster

La plupart des ralentissements réels ne se résument pas à « les UUID sont lents » ou « les bigint sont rapides ». C'est ce que la base doit toucher pour répondre à votre requête.

Les plans de requête tiennent surtout compte de la possibilité d'utiliser un index pour des filtres, d'effectuer des jointures rapides sur la clé, et de savoir si la table est physiquement ordonnée (ou assez proche) pour que les lectures de plage soient bon marché. Avec une clé primaire bigint, les nouvelles lignes arrivent dans un ordre croissant, donc l'index primaire tend à rester compact et favorable à la localité. Avec des UUID aléatoires, les insertions se dispersent, ce qui peut créer plus de page splits et un ordre sur disque plus désordonné.

Les lectures sont souvent le premier endroit où les équipes le remarquent. Des clés plus larges donnent des index plus grands, et des index plus grands signifient que moins de pages utiles tiennent en RAM. Cela réduit le taux de hit du cache et augmente l'I/O, surtout sur des écrans qui font beaucoup de jointures comme « lister les commandes avec les infos client ». Si votre working set ne tient pas en mémoire, des schémas riches en UUID peuvent vous pousser au‑delà de cette limite plus tôt.

Les écritures peuvent aussi être affectées. Les insertions avec UUID aléatoires augmentent le churn dans l'index, ce qui met plus de pression sur autovacuum et peut se traduire par des pics de latence pendant les périodes chargées.

Si vous comparez UUID vs bigint en bench, soyez honnête : même schéma, mêmes index, même fillfactor, et assez de lignes pour dépasser la RAM (pas 10k). Mesurez la latence p95 et l'I/O, testez cache chaud et froid.

Si vous développez des applications avec AppMaster sur PostgreSQL, ceci apparaît souvent comme des pages de liste plus lentes et une charge DB plus élevée bien avant que ce ne soit perçu comme un « problème CPU ».

Sécurité et utilisabilité dans les systèmes exposés au public

Si vos IDs sortent de la base et apparaissent dans des URLs, réponses API, tickets support ou écrans mobiles, le choix affecte à la fois la sécurité et l'ergonomie.

Les bigint sont simples pour les humains. Courts, lisibles au téléphone, et votre support peut repérer rapidement des motifs comme « tous les ordres en erreur sont autour de 9 200 000 ». Cela accélère le debug, surtout quand on travaille à partir de logs ou de captures d'écran clients.

Les UUID sont utiles quand vous exposez des identifiants publiquement. Un UUID est difficile à deviner : parcourir /users/1, /users/2, /users/3 ne fonctionne pas. Il est aussi plus difficile pour un tiers d'inférer combien d'enregistrements vous avez.

Le piège est de croire qu'« indévinable » rime avec « sécurisé ». Si les vérifications d'autorisation sont faibles, des bigint prévisibles peuvent être abusés, mais des UUID peuvent tout autant être volés via un lien partagé, un log divulgué ou une réponse API en cache. La sécurité doit venir des vérifications d'accès, pas du secret des IDs.

Approche pratique :

  • Appliquez des vérifications d'appartenance ou de rôle sur chaque lecture et écriture.
  • Si vous exposez des IDs dans des APIs publiques, utilisez des UUIDs ou des tokens publics séparés.
  • Si vous voulez des références lisibles en interne, conservez un bigint interne pour l'exploitation.
  • N'encodiez pas de sens sensible dans l'ID lui‑même (comme le type d'utilisateur).

Exemple : un portail client affiche des factures. Si les factures utilisent des bigint et que votre API se contente de vérifier « invoice exists », quelqu'un peut itérer les numéros et télécharger les factures des autres. Corrigez d'abord la vérification. Ensuite, décidez si des UUIDs pour les IDs publics réduisent le risque et la charge support.

Sur des plateformes comme AppMaster, où les IDs circulent dans des APIs générées et des apps mobiles, la valeur sûre est une autorisation cohérente plus un format d'ID que les clients gèrent sans surprise.

Comment les IDs transitent dans les APIs et les applis mobiles

Livrez sans vous verrouiller trop tôt
Déployez sur le cloud ou exportez le code source quand vous êtes prêt à héberger vous-même.
Déployer maintenant

Le type choisi en base ne reste pas confiné à la base. Il fuit à chaque frontière : URLs, payloads JSON, stockage client, logs et analytics.

Changer le type plus tard n'est rarement « juste une migration ». Les clés étrangères doivent être modifiées partout, pas seulement dans la table principale. Les ORM et générateurs peuvent régénérer des modèles, mais les intégrations s'attendent encore à l'ancien format. Même un simple GET /users/123 devient compliqué quand l'ID devient un UUID de 36 caractères. Il faut aussi mettre à jour caches, files de messages et tout endroit où les IDs étaient stockés en tant qu'entiers.

Pour les APIs, le choix principal est le format et la validation. Les bigint circulent comme nombres, mais certains systèmes (et langages) risquent des problèmes de précision si elles sont parsées en flottants. Les UUIDs circulent comme chaînes, ce qui est souvent plus sûr pour le parsing, mais exige une validation stricte pour éviter des « quasi‑UUID » qui polluent logs et base.

Sur mobile, les IDs sont constamment sérialisés et stockés : réponses JSON, SQLite local, files d'actions hors‑ligne qui attendent le réseau. Les IDs numériques sont plus petits, mais les UUIDs en chaîne sont souvent plus faciles à traiter comme tokens opaques. Le vrai problème vient de l'incohérence : une couche stocke en entier, une autre en texte, et les comparaisons ou jointures deviennent fragiles.

Règles simples pour éviter les ennuis :

  • Choisissez une représentation canonique pour l'API (souvent string) et tenez‑vous y.
  • Validez les IDs dès la frontière et retournez des 400 clairs.
  • Stockez la même représentation dans le cache local et les files hors‑ligne.
  • Loggez les IDs avec des noms de champs et formats constants entre services.

Si vous générez des clients web et mobiles (par exemple avec AppMaster), un contrat d'ID stable est d'autant plus crucial qu'il devient partie intégrante de chaque modèle et requête générés.

Préparation au sharding et systèmes distribués

« Prêt pour le sharding » signifie surtout pouvoir créer des IDs en plusieurs endroits sans casser l'unicité, et déplacer des données entre nœuds plus tard sans réécrire toutes les clés étrangères.

Les UUIDs sont populaires en multi‑région ou multi‑writer parce que chaque nœud peut générer un ID unique sans coordonner une séquence centrale. Cela réduit la coordination et facilite l'acceptation d'écritures dans différentes régions et la fusion des données ensuite.

Le bigint peut fonctionner, mais il faut un plan. Options courantes : allouer des plages numériques par shard (shard 1 utilise 1–1G, shard 2 utilise 1G–2G), exécuter des séquences séparées avec un préfixe shard, ou utiliser des IDs style Snowflake (bits temps + bits machine). Ces approches maintiennent des index plus petits que des UUIDs et préservent un certain ordre, mais elles ajoutent des règles opérationnelles à appliquer.

Compromis à considérer :

  • Coordination : UUID en demande presque aucune ; bigint demande souvent planification de plages ou un service générateur.
  • Collisions : les UUID sont extrêmement peu susceptibles de collision ; le bigint est sûr uniquement si les règles d'allocation ne se chevauchent jamais.
  • Ordre : beaucoup de schémas bigint sont approximativement ordonnés par le temps ; les UUID le sont rarement sauf si vous utilisez une variante ordonnée dans le temps.
  • Complexité : le bigint shardé reste simple uniquement si l'équipe est disciplinée.

Pour beaucoup d'équipes, « prêt pour le sharding » signifie en réalité « prêt à migrer ». Si vous êtes sur une base unique aujourd'hui, choisissez l'ID qui rend le travail courant plus facile. Si vous construisez déjà des writers multiples (par exemple via des APIs et apps mobiles générées dans AppMaster), décidez tôt comment les IDs sont créés et validés à travers les services.

Étapes pour choisir la bonne stratégie d'ID

Ajoutez des contrôles d'accès appropriés
Implémentez validation et autorisation sans compter sur des IDs difficiles à deviner.
Utiliser l'éditeur BP

Commencez par décrire honnêtement la forme réelle de votre application. Une seule base PostgreSQL dans une région n'a pas les mêmes besoins qu'un système multi‑tenant, un setup susceptible d'être fragmenté par région, ou une app mobile qui doit créer des enregistrements hors‑ligne et synchroniser ensuite.

Ensuite, soyez clair sur les lieux où les IDs apparaîtront. Si les identifiants restent dans votre backend (jobs, outils internes, panneaux admin), la simplicité gagne souvent. Si les IDs apparaissent dans des URLs, logs partagés avec des clients, tickets support ou deep links mobiles, la prévisibilité et la confidentialité comptent davantage.

Utilisez l'ordonnancement comme critère de décision, pas comme après‑coup. Si vous comptez sur des flux « newest first », une pagination stable, ou des audits faciles à parcourir, des IDs séquentiels (ou ordonnés dans le temps) réduisent les surprises. Si l'ordre n'est pas lié à la clé primaire, vous pouvez conserver le choix du PK et trier par un timestamp séparé.

Un flux de décision pratique :

  1. Classifiez votre architecture (DB unique, multi‑tenant, multi‑région, offline‑first) et si vous pourriez fusionner des données venant de sources multiples.
  2. Décidez si les IDs seront publics ou purement internes.
  3. Confirmez vos besoins en tri et pagination. Si vous avez besoin d'un ordre d'insertion naturel, évitez les IDs purement aléatoires.
  4. Si vous choisissez les UUID, choisissez une version volontairement : aléatoire (v4) pour l'imprévisibilité, ou ordonné dans le temps pour une meilleure localité d'index.
  5. Verrouillez les conventions tôt : une forme textuelle canonique, règles de casse, validation, et comment chaque API retourne et accepte les IDs.

Exemple : si une app mobile crée des « commandes brouillon » hors‑ligne, les UUID permettent au dispositif de générer des IDs en toute sécurité avant que le serveur ne voie la donnée. Dans des outils comme AppMaster, c'est aussi pratique car le même format d'ID peut circuler de la base à l'API puis vers les apps web et natives sans traitement spécifique.

Pièges courants à éviter

Cartographiez vos clés et vos clés étrangères
Concevez visuellement tables, clés et relations avant d'écrire du code.
Ouvrir le concepteur de données

La plupart des débats sur les IDs tournent mal parce que les équipes choisissent un type pour une raison, puis sont surprises par des effets secondaires inattendus.

Une erreur fréquente est d'utiliser des UUIDs complètement aléatoires sur une table très sollicitée en écriture, puis de s'étonner d'inserts spikés. Les valeurs aléatoires dispersent les nouvelles lignes dans l'index, augmentant page splits et travail pour la base. Si la table est write‑heavy, pensez à la localité des insertions avant de trancher.

Un autre problème courant est de mélanger les types d'ID entre services et clients. Par exemple, un service utilise bigint, un autre UUID, et votre API se retrouve avec des IDs numériques et des chaînes. Cela mène souvent à des bugs subtils : parsers JSON qui perdent de la précision sur de grands nombres, code mobile qui traite les IDs comme nombres dans un écran et comme chaînes dans un autre, ou clés de cache qui ne correspondent pas.

Un troisième piège est de considérer des IDs « indévinables » comme une sécurité. Même avec des UUIDs, il faut des vérifications d'autorisation appropriées.

Enfin, les équipes changent le type d'ID tard sans plan. La partie la plus difficile n'est pas la colonne PK elle‑même, mais tout ce qui y est attaché : clés étrangères, tables de jointure, URLs, événements analytics, deep links mobiles, et l'état stocké côté client.

Pour éviter la douleur :

  • Choisissez un type d'ID unique pour les APIs publiques et tenez‑vous y.
  • Traitez les IDs comme des chaînes opaques côté client pour éviter les cas limites numériques.
  • N'utilisez jamais l'aléa de l'ID comme contrôle d'accès.
  • Si vous devez migrer, versionnez l'API et planifiez pour des clients long‑temps en service.

Si vous développez avec une plateforme génératrice comme AppMaster, la cohérence compte d'autant plus que le même type d'ID circule du schéma de base vers le backend généré et les apps web et mobiles.

Checklist rapide avant de décider

Si vous êtes coincé, ne commencez pas par la théorie. Commencez par ce à quoi votre produit ressemblera dans un an, et par combien d'endroits cet ID va circuler.

Interrogez‑vous :

  • Quelle taille auront les plus grandes tables dans 12–24 mois, et garderez‑vous des années d'historique ?
  • Avez‑vous besoin d'IDs qui s'ordonnent à peu près par date de création pour faciliter le paging et le debug ?
  • Plus d'un système créera‑t‑il des enregistrements en même temps, y compris des apps mobiles hors‑ligne ou des jobs background ?
  • L'ID apparaîtra‑t‑il dans des URLs, tickets support, exports ou captures d'écran partagées avec des clients ?
  • Chaque client peut‑il traiter l'ID de la même façon (web, iOS, Android, scripts), y compris validation et stockage ?

Après avoir répondu, vérifiez la plomberie. Si vous utilisez bigint, assurez‑vous d'un plan clair pour la génération d'IDs dans tous les environnements (dev local et imports inclus). Si vous utilisez UUID, assurez‑vous que vos contrats API et modèles clients gèrent les IDs en tant que chaînes de façon cohérente, et que l'équipe sait lire et comparer ces valeurs.

Test de réalité rapide : si une app mobile doit créer une commande hors‑ligne et synchroniser ensuite, les UUID réduisent souvent le travail de coordination. Si votre appli est majoritairement en ligne et que vous voulez des index compacts, bigint est généralement plus simple.

Si vous créez des apps dans AppMaster (appmaster.io), décidez tôt : la convention d'ID traverse votre modèle PostgreSQL, les APIs générées et les clients natifs et web.

Scénario réaliste

Prototyper des pages de liste et des jointures
Validez le comportement des index et de la pagination avec des données et écrans réalistes.
Construire un prototype

Une petite société a un outil opérationnel interne, un portail client et une app mobile pour le personnel terrain. Les trois accèdent à la même base PostgreSQL via une API. De nouveaux enregistrements arrivent toute la journée : tickets, photos, statuts et factures.

Avec bigint, les payloads API sont compacts et faciles à lire :

{ "ticket_id": 4821931, "customer_id": 91244 }

La pagination est naturelle : ?after_id=4821931&limit=50. Le tri par id correspond souvent au temps de création, donc « derniers tickets » est rapide et prévisible. Le debug est simple : le support peut demander « ticket 4821931 » et la plupart des gens peuvent le taper sans erreur.

Avec UUIDs, les payloads s'allongent :

{ "ticket_id": "3f9b3c0a-7b9c-4bf0-9f9b-2a1b3c5d1d2e" }

Avec des v4 aléatoires, les insertions se rependent dans l'index. Cela peut induire davantage de churn d'index et rendre le debug quotidien un peu moins fluide (copier/coller devient la norme). La pagination bascule souvent sur des curseurs plutôt que sur un simple « after id ».

Si vous utilisez des UUIDs ordonnés dans le temps, vous gardez la plupart des comportements « newest first » tout en évitant des IDs devinables en public.

En pratique, les équipes remarquent quatre choses :

  • À quelle fréquence les IDs sont tapés par des humains vs copiés
  • Si « trier par id » correspond à « trier par created »
  • La propreté et stabilité de la pagination par curseur
  • La facilité à tracer un enregistrement entre logs, appels API et écrans mobiles

Étapes suivantes : choisissez une valeur par défaut, testez‑la et normalisez

La plupart des équipes veulent une réponse parfaite. Vous n'en avez pas besoin. Choisissez une valeur par défaut adaptée à votre produit aujourd'hui, et une manière rapide de prouver qu'elle ne vous bloquera pas plus tard.

Règles à standardiser :

  • Utilisez bigint quand vous voulez des index plus petits, un ordre prévisible et un débogage facile.
  • Utilisez UUID quand les IDs doivent être difficiles à deviner dans les URLs, que vous attendez une création hors‑ligne (mobile), ou que vous voulez moins de collisions entre systèmes.
  • Si vous pouvez fragmenter les données par tenant ou région plus tard, préférez un plan d'ID qui fonctionne sur plusieurs nœuds (UUID, ou un schéma bigint coordonné).
  • Choisissez une option par défaut et limitez les exceptions. La cohérence bat souvent l'optimisation fine pour une table.

Avant de verrouiller le choix, faites un petit spike. Créez une table avec une taille de ligne réaliste, insérez 1 à 5 millions de lignes et comparez : (1) taille des index, (2) temps d'insertion, (3) quelques requêtes courantes avec la clé primaire et quelques index secondaires. Faites‑le sur votre matériel réel et avec votre forme de données.

Si vous craignez de devoir changer plus tard, planifiez une migration peu risquée :

  • Ajoutez la nouvelle colonne d'ID et un index unique.
  • Écrivez en double : remplissez les deux IDs pour les nouvelles lignes.
  • Rétro‑remplissez les anciennes lignes par lots.
  • Mettez à jour APIs et clients pour accepter le nouvel ID (conservez l'ancien pendant la transition).
  • Basculez les lectures, puis supprimez l'ancienne clé quand les logs et métriques sont propres.

Si vous développez sur AppMaster (appmaster.io), décidez tôt : la convention d'ID traverse votre modèle PostgreSQL, les APIs générées et les apps web et natives. Le type importe, mais la cohérence compte souvent plus quand vous avez de vrais utilisateurs et plusieurs clients.

FAQ

Dois‑je utiliser bigint ou UUID comme clé primaire dans PostgreSQL ?

Par défaut, choisissez bigint quand vous avez une seule base PostgreSQL, que la plupart des écritures se font côté serveur, et que vous privilégiez des index compacts et un comportement d'insertion prévisible. Optez pour les UUID quand les identifiants doivent être générés en de nombreux endroits (services multiples, mobile hors-ligne, sharding futur) ou quand vous ne voulez pas que les IDs publics soient faciles à deviner.

Pourquoi les UUID font-ils tant grossir les index et le stockage ?

Parce que l'ID est copié à de nombreux endroits : index de la clé primaire, chaque index secondaire (comme pointeur vers la ligne), colonnes de clés étrangères dans d'autres tables et tables de jointure. Les UUID font 16 octets contre 8 pour bigint, donc la différence de taille se multiplie à travers votre schéma et peut réduire les taux de cache.

Les UUID ralentissent-ils les insertions comparé aux bigint ?

Sur les tables à forts taux d'insertion, oui. Les UUID aléatoires (comme v4) dispersent les insertions dans tout le B-tree, ce qui augmente les éclatements de pages et l'usure des index sous charge. Si vous voulez des UUID tout en ayant des écritures plus lisses, utilisez une stratégie d'UUID ordonnés dans le temps pour que les nouvelles clés arrivent majoritairement en fin d'index.

Remarquerai‑je des lectures plus lentes avec des UUID ?

On le remarque souvent sous forme d'I/O davantage que de ralentissement CPU. Des clés plus larges donnent des index plus grands, et des index plus grands signifient que moins de pages tiennent en mémoire, donc les jointures et recherches entraînent plus de lectures. La différence est la plus visible sur de grandes tables, les requêtes avec beaucoup de jointures, et quand l'ensemble de travail ne tient pas en RAM.

Les UUID sont-ils plus sécurisés que les bigint dans les APIs publiques ?

Les UUID réduisent les tentatives de deviner des URLs comme /users/1, mais ils ne remplacent pas les contrôles d'autorisation. Si vos vérifications d'accès sont incorrectes, des UUIDs peuvent toujours être divulgués et réutilisés. Considérez les UUID comme une commodité pour les identifiants publics ; la sécurité réelle repose sur des contrôles d'accès stricts.

Quelle est la meilleure façon de représenter les IDs dans les APIs JSON ?

Utilisez une seule représentation canonique et respectez‑la. Un choix pratique est de traiter les IDs comme des chaînes dans les requêtes et réponses API, même si la base utilise bigint, car cela évite les problèmes numériques côté client et simplifie la validation. Quoi que vous choisissiez, soyez cohérent sur le web, le mobile, les logs et les caches.

Les bigint posent‑ils des problèmes en JavaScript ou sur mobile ?

Les bigint peuvent poser problème dans certains clients si elles sont parsées comme des nombres à virgule flottante, ce qui fait perdre en précision pour de grandes valeurs. Les UUID évitent ce problème car ce sont des chaînes, mais ils sont plus longs et peuvent être mal gérés si vous ne validez pas strictement. L'approche la plus sûre : la cohérence — un même type partout, avec une validation claire à l'entrée.

Que choisir si je risque de sharder ou d'aller multi‑région plus tard ?

Les UUID sont un choix simple car chaque nœud peut générer des IDs uniques sans consulter une séquence centrale. Les bigint fonctionnent aussi, mais vous devez définir des règles (plages par shard, préfixe shard, ou générateurs de style Snowflake) et les appliquer rigoureusement. Si vous voulez la solution distribuée la plus simple, choisissez les UUID (de préférence ordonnés par le temps).

Quelle est la difficulté de migrer de bigint à UUID (ou inversement) ?

Changer le type de clé primaire touche bien plus qu'une colonne. Il faut mettre à jour les clés étrangères, les tables de jointure, les contrats d'API, le stockage côté client, les caches, les événements d'analytics, et toute intégration ayant stocké les IDs comme nombres ou chaînes. Si un changement est probable, planifiez une migration progressive avec écriture duale et une longue fenêtre de transition.

Puis‑je utiliser les deux : bigint en interne et UUID en externe ?

Gardez une clé bigint interne pour l'efficacité en base, et ajoutez un UUID public (ou un token) séparé pour les URLs et APIs externes. Vous bénéficiez ainsi d'index compacts et d'un débogage convivial en interne tout en évitant l'énumération facile sur l'interface publique. L'important : définissez tôt lequel est l'« ID public » et ne les mélangez pas sans précaution.

Facile à démarrer
Créer quelque chose d'incroyable

Expérimentez avec AppMaster avec un plan gratuit.
Lorsque vous serez prêt, vous pourrez choisir l'abonnement approprié.

Démarrer