Que pensez-vous de l'utilisation des UUID comme identifiants de lignes de bases de données, en particulier dans les applications Web ?

StackOverflow https://stackoverflow.com/questions/5949

  •  08-06-2019
  •  | 
  •  

Question

J'ai toujours préféré utiliser des entiers longs comme clés primaires dans les bases de données, pour des raisons de simplicité et de rapidité (supposée).Mais lorsque l'on utilise un REPOS ou un schéma d'URL de type Rails pour les instances d'objet, je me retrouverais alors avec des URL comme celle-ci :

http://example.com/user/783

Et puis l'hypothèse est qu'il existe également des utilisateurs avec les identifiants 782, 781, ..., 2 et 1.En supposant que l'application Web en question est suffisamment sécurisée pour empêcher les personnes de saisir d'autres numéros pour voir d'autres utilisateurs sans autorisation, une simple clé de substitution attribuée séquentiellement « divulgue » également le nombre total d'instances (plus anciennes que celle-ci), dans ce cas les utilisateurs. , qui pourrait être une information privilégiée.(Par exemple, je suis l'utilisateur n°726 dans stackoverflow.)

Est-ce qu'un UUID/GUID est-il une meilleure solution ?Ensuite, je pourrais configurer des URL comme ceci :

http://example.com/user/035a46e0-6550-11dd-ad8b-0800200c9a66

Pas exactement succinct, mais il y a moins d’informations implicites sur les utilisateurs affichées.Bien sûr, cela sent la « sécurité par l’obscurité », qui ne remplace pas une sécurité adéquate, mais cela semble au moins un peu plus sûr.

Cet avantage vaut-il le coût et la complexité de la mise en œuvre des UUID pour les instances d'objets adressables sur le Web ?Je pense que je voudrais toujours utiliser des colonnes entières comme PK de base de données juste pour accélérer les jointures.

Il y a aussi la question de la représentation des UUID dans la base de données.Je sais que MySQL les stocke sous forme de chaînes de 36 caractères.Postgres semble avoir une représentation interne plus efficace (128 bits ?) mais je ne l'ai pas essayé moi-même.Quelqu'un a-t-il une expérience avec ceci?


Mise à jour:pour ceux qui ont demandé à utiliser simplement le nom d'utilisateur dans l'URL (par exemple, http://example.com/user/yukondude), qui fonctionne bien pour les instances d'objets dont les noms sont uniques, mais qu'en est-il des millions d'objets d'application Web qui ne peuvent en réalité être identifiés que par un numéro ?Commandes, transactions, factures, noms d'images en double, questions de stackoverflow, ...

Était-ce utile?

La solution

Je ne peux pas parler du côté Web de votre question.Mais les uuids sont parfaits pour les applications à plusieurs niveaux.La génération PK peut être décentralisée :chaque client génère son propre pk sans risque de collision.Et la différence de vitesse est généralement faible.

Assurez-vous que votre base de données prend en charge un type de données de stockage efficace (16 octets, 128 bits).À tout le moins, vous pouvez encoder la chaîne uuid en base64 et utiliser char(22).

Je les ai largement utilisés avec Firebird et je les recommande.

Autres conseils

Pour ce que ça vaut, j'ai vu une procédure stockée de longue durée (plus de 9 secondes) chuter à seulement quelques centaines de millisecondes de temps d'exécution simplement en passant des clés primaires GUID aux entiers.Cela ne veut pas dire affichage un GUID est une mauvaise idée, mais comme d'autres l'ont souligné, les rejoindre et les indexer, par définition, ne sera pas aussi rapide qu'avec des nombres entiers.

Je peux vous répondre que dans SQL Server, si vous utilisez un type de données uniqueidentifier (GUID) et utilisez la fonction NEWID() pour créer des valeurs, vous obtiendrez une fragmentation horrible à cause des fractionnements de page.La raison est que lors de l'utilisation de NEWID(), la valeur générée n'est pas séquentielle.SQL 2005 a ajouté la fonction NEWSEQUANTIAL() pour remédier à ce problème

Une façon de continuer à utiliser GUID et int consiste à avoir un guid et un int dans une table afin que le guid corresponde à l'int.le guid est utilisé en externe mais le int en interne dans la base de données

Par exemple

457180FB-C2EA-48DF-8BEF-458573DA1C10    1
9A70FF3C-B7DA-4593-93AE-4A8945943C8A    2

1 et 2 seront utilisés dans les jointures et les guids de l'application Web.Ce tableau sera assez étroit et devrait être assez rapide à interroger

Pourquoi coupler votre clé primaire avec votre URI ?

Pourquoi ne pas faire en sorte que votre clé URI soit lisible par l'homme (ou impossible à deviner, selon vos besoins) et que votre index principal soit basé sur un nombre entier, de cette façon vous obtenez le meilleur des deux mondes.De nombreux logiciels de blog font cela, où l'identifiant exposé de l'entrée est identifié par un « slug » et l'identifiant numérique est caché à l'intérieur du système.

L’avantage supplémentaire ici est que vous disposez désormais d’une très belle structure d’URL, ce qui est bon pour le référencement.Évidemment, pour une transaction, ce n'est pas une bonne chose, mais pour quelque chose comme stackoverflow, c'est important (voir URL en haut...).Obtenir l'unicité n'est pas si difficile.Si vous êtes vraiment inquiet, stockez un hachage du slug quelque part dans une table et effectuez une recherche avant l'insertion.

modifier: Stackoverflow n'utilise pas vraiment le système que je décris, voir le commentaire de Guy ci-dessous.

Plutôt que des URL comme celle-ci :

http://example.com/user/783

Pourquoi ne pas avoir :

http://example.com/user/yukondude

Qu'est-ce qui est le plus convivial pour les humains et ne divulgue pas ce petit bout d'information ?

Vous pouvez utiliser un entier lié au numéro de ligne mais qui n'est pas séquentiel.Par exemple, vous pouvez prendre les 32 bits de l'ID séquentiel et les réorganiser selon un schéma fixe (par exemple, le bit 1 devient le bit 6, le bit 2 devient le bit 15, etc.).
Il s'agira d'un cryptage bidirectionnel, et vous serez sûr que deux identifiants différents auront toujours des cryptages différents.
Ce serait évidemment facile à décoder, si l'on prend le temps de générer suffisamment d'identifiants et d'obtenir le schéma, mais, si je comprends bien votre problème, vous voulez simplement ne pas divulguer d'informations trop facilement.

Nous utilisons les GUID comme clés primaires pour toutes nos tables, car ils servent également de RowGUID pour la réplication MS SQL Server.Cela rend les choses très faciles lorsque le client ouvre soudainement un bureau dans une autre partie du monde...

Je ne pense pas qu'un GUID vous apporte beaucoup d'avantages.Les utilisateurs détestent les URL longues et incompréhensibles.

Créez un identifiant plus court que vous pouvez mapper à l'URL ou appliquez une convention de nom d'utilisateur unique (http://example.com/user/brianly).Les gars à 37Signaux se moquerait probablement de vous si vous vous inquiétez de quelque chose comme ça lorsqu'il s'agit d'une application Web.

Par ailleurs, vous pouvez forcer votre base de données à commencer à créer des identifiants entiers à partir d'une valeur de base.

Cela dépend aussi de ce qui vous intéresse pour votre candidature.Pour les applications à plusieurs niveaux, les GUID/UUID sont plus simples à implémenter et plus faciles à porter entre différentes bases de données.Pour produire des clés entières, certaines bases de données prennent en charge un objet séquence de manière native et certaines nécessitent la construction personnalisée d'une table de séquence.

Les clés entières (je n'ai pas de chiffres) offrent probablement un avantage en termes de performances de requête et d'indexation ainsi que d'utilisation de l'espace.L'interrogation directe de la base de données est également beaucoup plus facile à l'aide de touches numériques, moins de copier/coller car elles sont plus faciles à mémoriser.

Je travaille avec un système de gestion des étudiants qui utilise les UUID sous la forme d'un nombre entier.Ils ont une table qui contient le prochain identifiant unique.

Bien que ce soit probablement une bonne idée d’un point de vue architectural, cela rend le travail quotidien difficile.Parfois, il est nécessaire d'effectuer des insertions en masse et le fait d'avoir un UUID rend cela très difficile, nécessitant généralement l'écriture d'un curseur au lieu d'une simple instruction SELECT INTO.

J'ai essayé les deux dans de vraies applications Web.

Mon avis est qu'il est préférable d'utiliser des nombres entiers et d'avoir des URL courtes et compréhensibles.

En tant que développeur, c'est un peu horrible de voir des entiers séquentiels et de savoir que certaines informations sur le nombre total d'enregistrements sont divulguées, mais honnêtement, la plupart des gens s'en moquent probablement, et ces informations n'ont jamais vraiment été critiques pour mon entreprise.

Avoir de longues URL UUID laides me semble être beaucoup plus décourageant pour les utilisateurs normaux.

Je pense que c’est l’une de ces questions qui suscitent des débats quasi religieux, et dont il est presque inutile d’en parler.Je dirais simplement d'utiliser ce que vous préférez.Dans 99 % des systèmes, peu importe le type de clé que vous utilisez, les avantages (indiqués dans les autres articles) de l'utilisation d'un type par rapport à l'autre ne seront jamais un problème.

Je pense que l'utilisation d'un GUID serait le meilleur choix dans votre situation.Cela prend plus de place mais c'est plus sécurisé.

Youtube utilise 11 caractères avec un encodage base64 qui offre 11 ^ 64 possibilités, et ils sont généralement assez faciles à écrire.Je me demande si cela offrirait de meilleures performances qu'un UUID complet.L'UUID converti en base 64 serait le double de la taille, je crois.

Plus d'informations peuvent être trouvées ici: https://www.youtube.com/watch?v=gocwRvLhDf8

Tant que vous utilisez un système de base de données avec un stockage efficace, le disque dur est de toute façon bon marché de nos jours...

Je sais que les GUID peuvent parfois être difficiles à utiliser et entraîner une surcharge de requêtes, mais du point de vue de la sécurité, ils sont un sauveur.

En pensant à la sécurité par l'obscurité, ils s'intègrent bien lors de la formation d'URI obscurs et de la construction de bases de données normalisées avec une sécurité définie par table, enregistrement et colonne, vous ne pouvez pas vous tromper avec les GUID, essayez de le faire avec des identifiants basés sur des nombres entiers.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top