9 min de lecture

UUID vs GUID : différences et compatibilité

Découvrez si l'UUID et le GUID sont identiques, comprenez les pièges d'endianness entre .NET et la RFC 4122, et choisissez le bon format pour votre stack.

Lors de la modélisation d'une base de données, de files de messages ou d'APIs distribuées, les développeurs rencontrent constamment deux dénominations : UUID (Universally Unique Identifier) et GUID (Globally Unique Identifier). S'agit-il de deux technologies rivales, de synonymes parfaits ou d'implémentations subtilement incompatibles ?

La réponse directe est la suivante : dans leur représentation textuelle, l'UUID et le GUID désignent exactement le même identifiant de 128 bits. Un GUID aléatoire standard généré dans l'écosystème Microsoft .NET est textuellement équivalent à un UUID v4 standardisé par la RFC 4122 sous Linux, Java, Python ou PostgreSQL. Cependant, sous le capot réside un piège technique majeur : le stockage binaire de Microsoft utilise un agencement à endianness mixte (mixed-endian), ce qui produit des inversions d'octets lors du transfert de données binaires brutes entre .NET et les autres plateformes.

Vous pouvez générer et formater ces identifiants avec le générateur de GUID ou le générateur d'UUID de ToolPorta. Ce guide retrace leurs origines, explique le piège des tableaux d'octets en endianness mixte et donne des règles d'interopérabilité concrètes.

Format et structure textuelle#

L'UUID et le GUID reposent tous deux sur une valeur brute de 128 bits (16 octets). Sous forme de chaîne de caractères, ils sont représentés par 32 chiffres hexadécimaux séparés par des tirets en 5 groupes selon le modèle canonique 8-4-4-4-12 (soit 36 caractères au total) :

TEXT
1xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx2|      |   |   |   |           |
  • Groupe 1 (8 car. hexadécimaux / 32 bits) : Horodatage bas ou données pseudo-aléatoires.
  • Groupe 2 (4 car. hexadécimaux / 16 bits) : Horodatage intermédiaire ou aléa.
  • Groupe 3 (4 car. hexadécimaux / 16 bits) : Horodatage haut combiné au numéro de version M sur 4 bits (par exemple 4 pour l'aléa pur, 7 pour le tri temporel).
  • Groupe 4 (4 car. hexadécimaux / 16 bits) : Champ de variante N (généralement 8, 9, a ou b selon la variante standard DCE/RFC) et séquence d'horloge ou aléa.
  • Groupe 5 (12 car. hexadécimaux / 48 bits) : Adresse MAC du nœud (dans la version 1) ou entropie pseudo-aléatoire cryptographiquement sûre (dans la version 4).

Différences de conventions stylistiques#

Bien que la valeur numérique de 128 bits soit identique, les deux écosystèmes appliquent des conventions de présentation distinctes :

CaractéristiqueUUID standard (RFC 4122 / RFC 9562)GUID Microsoft (Windows / .NET / COM)
Casse des lettresHexadécimal majuscule, minuscule ou mixte acceptéSouvent affiché en majuscules dans les exemples Microsoft
Accolades délimitatricesSans accolades (e04f...)Fréquemment encadré d'accolades ({E04F...})
Valeur nulle / videNil UUID (00000000-0000-0000-0000-000000000000)Guid.Empty (00000000-0000-0000-0000-000000000000)
Écosystème prédominantAPIs REST, Linux, Java, Python, Go, PostgreSQLC#, F#, .NET, Registre Windows, COM, SQL Server

Dans les APIs JSON, choisir une forme canonique — souvent minuscules, tirets et sans accolades — simplifie comparaison et journalisation. La casse ne change pas la valeur de 128 bits.

Le piège critique : L'endianness binaire mixte#

Le piège le plus redoutable pour les ingénieurs survient lorsque des identifiants sont transférés ou persistés sous forme d'octets binaires bruts (tableaux de 16 octets) au lieu de chaînes de caractères.

L'héritage de la structure C Win32#

Dans les fichiers d'en-tête historiques de Windows (guiddef.h), un GUID n'a pas été défini comme un simple tableau séquentiel de 16 octets, mais comme une structure C composite :

C
1typedef struct _GUID {2    unsigned long  Data1;    // Entier non signé de 32 bits (4 octets)3    unsigned short Data2;    // Entier non signé de 16 bits (2 octets)4    unsigned short Data3;    // Entier non signé de 16 bits (2 octets)5    unsigned char  Data4[]; // Tableau de 8 octets individuels6} GUID;

Or, les processeurs x86 et x64 fonctionnent en mode petit-boutiste (little-endian) : les entiers multi-octets sont stockés en mémoire en plaçant l'octet de poids faible en premier :

  • Data1 (4 octets) est enregistré en little-endian.
  • Data2 (2 octets) est enregistré en little-endian.
  • Data3 (2 octets) est enregistré en little-endian.
  • Data4 est un tableau d'octets individuels, stocké séquentiellement (big-endian).

À l'inverse, les normes IETF RFC 4122 et RFC 9562 imposent le format gros-boutiste (big-endian / network byte order) pour l'ensemble des 16 octets, calqué directement sur la lecture visuelle de gauche à droite de la chaîne hexadécimale.

Que se passe-t-il lors d'un appel à Guid.ToByteArray() ?#

Considérons l'identifiant valide suivant :

TEXT
1Représentation textuelle : --cdef--

Comparons le tableau de 16 octets produit selon la norme RFC 4122 (big-endian) et celui produit par la méthode par défaut .NET Guid.ToByteArray() sur une machine x86/x64 :

TEXT
1RFC  (Big-Endian standard) :2[ , , , ,   , ab,   cd, ef,   , ,   , , , ab, cd, ef ]3|--- Data1 ----|   |-Data2-| |-Data3-|  |----------- Data4 ------------|45.NET Guid.ToByteArray() (Endianness mixte) :6[ , , , ,   ab, ,   ef, cd,   , ,   , , , ab, cd, ef ]7|-- Inversé ---|   |-Inv.--| |-Inv.--|  |--------- Identique ----------|

Ce décalage a un impact concret immédiat :

  1. Les 4 premiers octets (Data1) sont inversés : 01 23 45 67 devient 67 45 23 01.
  2. Les 2 octets suivants (Data2) sont inversés : 89 ab devient ab 89.
  3. Les 2 octets suivants (Data3) sont inversés : cd ef devient ef cd.
  4. Les 8 derniers octets (Data4) restent strictement identiques.

Si un microservice .NET transmet ce tableau d'octets bruts via un message Kafka ou l'écrit dans un champ binaire, et qu'un service Java ou Go le relit selon la RFC 4122, il reconstituera une chaîne corrompue :

TEXT
1GUID .NET dorigine :      --cdef--2Interprété par Java / Go : -ab89-efcd--

L'identifiant ne correspond plus, les requêtes échouent et les jointures de clés primaires sont rompues.

Comment corriger ce problème d'endianness en .NET moderne#

Dans les versions modernes de .NET (.NET Core, .NET 8 et .NET 9), la classe System.Guid intègre des méthodes natives permettant de manipuler des octets au format big-endian standard :

C#
1// Export vers un tableau d'octets conforme à la RFC 4122 (big-endian) :2Guid guid = Guid.NewGuid();3byte[] rfcBytes = new byte[];4guid.TryWriteBytes(rfcBytes, bigEndian: true, out _);56// Lecture d'octets réseau standard au format RFC 4122 :7ReadOnlySpan<byte> octetsReseau = rfcBytes;8Guid guidReconstitue = new Guid(octetsReseau, bigEndian: true);

En règle générale, privilégiez la sérialisation textuelle sous forme de chaîne de 36 caractères avec tirets dans vos APIs et vos protocoles d'échange. Cela élimine définitivement toute ambiguïté matérielle liée au boutisme.

Comparatif des bases de données : SQL Server vs PostgreSQL vs MySQL#

Les systèmes de gestion de bases de données relationnelles gèrent les identifiants selon leur héritage technique :

1. Microsoft SQL Server (UNIQUEIDENTIFIER)#

SQL Server dispose du type natif UNIQUEIDENTIFIER, qui stocke 16 octets selon l'endianness mixte propre à Microsoft.

Le risque de fragmentation d'index : L'algorithme de tri interne de SQL Server pour UNIQUEIDENTIFIER compare en premier lieu les 6 derniers octets de Data4, puis les 2 premiers octets de Data4, puis Data3, Data2, et enfin Data1.

  • L'utilisation de NEWID() génère des valeurs aléatoires qui fragmentent lourdement les arbres B-tree sur les clés primaires clusterisées.
  • Pour atténuer ce phénomène, Microsoft a introduit NEWSEQUENTIALID(), qui génère des GUIDs séquentiels adaptés à cet ordre de tri spécifique.

2. PostgreSQL (uuid)#

PostgreSQL fournit le type natif uuid conforme aux spécifications de l'IETF. Il stocke les 16 octets au format gros-boutiste (big-endian) et effectue ses tris lexicographiquement.

  • PostgreSQL accepte les chaînes avec ou sans tirets, en majuscules ou minuscules, et encadrées d'accolades {...}.
  • Pour optimiser les performances d'écriture sur de gros volumes, consultez notre guide sur l'UUID v4 vs UUID v7 afin d'exploiter les identifiants ordonnés dans le temps.

3. MySQL et MariaDB#

MySQL ne dispose pas d'un type dédié unique :

  • VARCHAR(36) : Facile à inspecter, mais occupe 36 octets par ligne plus le surcoût d'indexation.
  • BINARY(16) : Très compact (16 octets). Les développeurs utilisent souvent la fonction UUID_TO_BIN(uuid, 1) pour réordonner les champs temporels de l'ancien UUID v1, ou y enregistrent directement des UUID v7 standardisés.

Tableau comparatif : UUID vs GUID#

Critère d'évaluationUUID (Norme IETF / RFC)GUID (Microsoft / .NET)
Organisme de normalisationIETF (RFC 4122, RFC 9562) & ISO/IECMicrosoft Corporation
Taille binaire128 bits (16 octets)128 bits (16 octets)
Format texte canonique8-4-4-4-12 avec tirets (36 caractères)8-4-4-4-12 avec tirets (36 caractères)
Casse du texteMajuscules, minuscules ou mélange validesMajuscules par convention historique
Délimiteurs {}Hors forme canonique RFC ; acceptés par certains parseursCourants dans le registre Windows et COM
Octets brutsChamps RFC en ordre réseauCOM historique et tableaux .NET par défaut en endianness mixte
Versions représentablesDispositions v1 à v8 de la RFC 9562Un Guid contient les mêmes 128 bits ; les APIs de génération dépendent de la plateforme
Types SQL natifsPostgreSQL uuid, CockroachDB uuidSQL Server uniqueidentifier
Échange textuel inter-plateformesFiable si les deux côtés acceptent la même syntaxeFiable sous forme textuelle canonique
Échange binaire brut (byte[])Définir explicitement l'ordre réseauConvertir les tableaux mixtes avant un échange au format RFC

Guide méthodologique : Bonnes pratiques d'interopérabilité#

Appliquez ces 4 recommandations pour fiabiliser la manipulation de vos identifiants :

  1. Privilégiez les chaînes textuelles aux frontières réseau : Échangez vos identifiants sous forme de chaînes canoniques de 36 caractères avec tirets dans vos APIs REST, requêtes GraphQL et documents JSON. Ne transmettez des tableaux d'octets que si le protocole binaire définit explicitement le schéma de sérialisation.
  2. Normalisez la casse lors de l'ingestion : Convertissez systématiquement les identifiants reçus en minuscules avant de les stocker dans des caches sensibles à la casse (comme Redis ou DynamoDB) pour éviter les doublons de clés.
  3. Supprimez les accolades avant d'insérer dans une URL : Si vous manipulez des GUIDs issus d'environnements Microsoft, retirez les accolades {} et les guillemets superflus à l'aide des options du générateur de GUID de ToolPorta pour éviter les encodages d'URL indésirables (%7B et %7D).
  4. Spécifiez explicitement le mode big-endian en C# : Si vous devez sérialiser des octets binaires depuis .NET, utilisez guid.TryWriteBytes(span, bigEndian: true) plutôt que la méthode historique guid.ToByteArray().

Foire aux questions#

Les identifiants UUID et GUID sont-ils interchangeables ?#

Leur texte canonique avec tirets représente généralement la même valeur de 128 bits. L'échange est fiable si les deux parties acceptent la même syntaxe et variante. Les accolades, variantes inhabituelles, politiques de parseur et tableaux d'octets exigent toujours un contrat explicite.

Pourquoi .NET inverse-t-il les octets des trois premiers blocs ?#

Au début des années 1990, Microsoft a défini le type GUID comme une structure C composée de trois entiers (unsigned long, unsigned short, unsigned short) et d'un tableau d'octets. Comme l'architecture x86 est petit-boutiste (little-endian), ces variables entières ont été stockées en mémoire avec leurs octets de poids faible en premier. La méthode historique ToByteArray() a fidèlement reproduit cette disposition interne.

Faut-il enregistrer ses identifiants en majuscules ou en minuscules en base ?#

Avec une colonne texte, normalisez vers une casse unique avant comparaison ; les minuscules sont une convention fréquente, pas une exigence RFC. Préférez si possible les types UUID/GUID natifs ou binaires de 16 octets et évitez plusieurs écritures textuelles d'une même valeur dans les stockages sensibles à la casse.

Peut-on insérer un GUID Microsoft dans une colonne UUID PostgreSQL ?#

Oui. Le moteur d'analyse de PostgreSQL accepte les identifiants en majuscules, en minuscules, avec ou sans tirets, ainsi que les valeurs encadrées par des accolades {...}. Il stocke ensuite la valeur interne de 128 bits selon la disposition gros-boutiste standard.

Les GUIDs supportent-ils la norme moderne UUID v7 ?#

Oui. .NET 9 a ajouté Guid.CreateVersion7(). Son horodatage en millisecondes améliore la localité par rapport à un GUID aléatoire, sans garantir l'absence totale de fragmentation : le résultat dépend toujours de l'index et de la charge.

Essayez les outils d'identifiants de ToolPorta#

Assurez une gestion rigoureuse et standardisée de vos identifiants grâce aux utilitaires en ligne de ToolPorta :

  • Utilisez le générateur de GUID pour produire des séries de GUIDs personnalisables avec accolades, majuscules, tirets et préfixes pour vos projets .NET et Windows.
  • Utilisez le générateur d'UUID pour créer des identifiants RFC 9562 UUID v7 et UUID v4 adaptés à vos microservices et bases de données.
  • Utilisez le générateur NanoID pour concevoir des identifiants compacts et sécurisés pour vos URLs web.
  • Consultez notre guide C# de GUID et des exemples UUID équivalents en JavaScript pour l'implémentation.
  • Découvrez notre article comparatif sur l'UUID v4 vs UUID v7 pour choisir un identifiant adapté à vos index relationnels.