J'utilise généralement des ID d'incrémentation automatique comme clés primaires dans les bases de données. J'essaie de découvrir les avantages de l'utilisation des GUID. J'ai lu cet article: https://betterexplained.com/articles/the-quick-guide-to-guids/
Je me rends compte que ces GUID sont utilisés pour identifier les objets au niveau de l'application. Sont-ils également stockés en tant que clé primaire au niveau de la base de données. Par exemple, disons que j'ai eu la classe suivante:
public class Person
{
public GUID ID;
public string Name;
..
//Person Methods follow
}
Disons que je voulais créer une nouvelle personne en mémoire, puis insérer la personne dans une base de données. Puis-je simplement faire ceci:
Person p1 = new Person();
p1.ID=GUID.NewGUID();
PersonRepository.Insert(p1);
Disons que j'avais une base de données contenant des millions et des millions de lignes avec un GUID comme clé primaire. Est-ce que ce sera toujours unique? Suis-je même comprendre correctement les GUID?
J'ai lu cet article plus tôt: http://enterprisecraftsmanship.com/2014/11/15/cqs-with-database-generated-ids/ . Cela m'embrouille un peu car il semble recommander un juste milieu entre les GUID et les entiers comme clés primaires.
Modifier le 11/06/18
J'en suis venu à croire que les Guids sont plus adaptés que les ints à mes besoins. J'utilise CQRS plus ces jours-ci et les GUID s'intègrent mieux.
Je remarque que certains développeurs modélisent les GUID sous forme de chaînes dans le modèle de domaine, par exemple ici: https://github.com/dotnet-architecture/eShopOnContainers/blob/dev/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/ Buyer.cs - dans ce cas: IdentityGuid est un GUID modélisé sous forme de chaîne. Y a-t-il une autre raison que celle indiquée ici: utiliser un objet de valeur personnalisé ou un GUID comme identifiant d'entité dans un système distribué? . Est-il «normal» de modéliser le GUID en tant que chaîne ou dois-je le modéliser en tant que GUID dans le modèle et la base de données?
la source
Réponses:
Les GUID sont par définition des "IDentifiants globalement uniques". Il existe un concept similaire mais légèrement différent en Java appelé UUID "Universally Unique IDentifiers". Les noms sont interchangeables pour toute utilisation pratique.
Les GUID sont au cœur de la façon dont Microsoft envisageait le clustering de bases de données, et si vous devez incorporer des données provenant de sources parfois connectées, elles aident vraiment à prévenir les collisions de données.
Quelques faits Pro-GUID:
Une certaine laideur avec les GUID
Les GUID augmenteront la taille de vos index, donc le coût d'espace disque pour l'indexation d'une colonne sera plus élevé. Les GUID aléatoires fragmenteront vos index.
Si vous savez que vous n'allez pas synchroniser les données de différents réseaux, les GUID peuvent entraîner plus de surcharge qu'ils n'en valent.
Si vous avez besoin d'ingérer des données de clients parfois connectés, ils peuvent être beaucoup plus robustes pour empêcher les collisions de clés que de dépendre de la définition de plages de séquences pour ces clients.
la source
Toujours? non, pas toujours; c'est une séquence finie de bits.
Des millions et des millions, vous êtes probablement en sécurité. Un million de millions, et la probabilité d'une collision devient importante. Il y a cependant une bonne nouvelle: vous avez déjà épuisé l'espace disque au moment où cela se produit.
Vous pouvez; ce n'est pas une très bonne idée. Votre modèle de domaine ne devrait normalement pas générer de nombres aléatoires; ils doivent être des entrées pour votre modèle.
Au-delà de cela, lorsque vous traitez avec un réseau peu fiable, où vous pouvez obtenir des messages en double, un UUID généré de manière déterministe vous protégera contre la présence d'entités en double. Mais si vous attribuez un nouveau nombre aléatoire à chacun, vous avez plus de travail à faire pour identifier la duplication.
Voir la description de l'uuid basé sur le nom dans la RFC 4122
Je ne pense pas que cela compte beaucoup. Pour la plupart de votre modèle de domaine, c'est un identifiant ; la seule question que vous lui demandez est de savoir si elle est ou non identique à un autre identifiant. Votre modèle de domaine ne regarde normalement pas la représentation en mémoire d'un identifiant.
Si le GUID est disponible en tant que «type primitif» dans votre paramètre indépendant de domaine, je l'utilise; il permet au contexte de prise en charge de choisir les optimisations appropriées qui peuvent être disponibles.
Ce que vous devez reconnaître, cependant, c'est que la représentation de l'identifiant, à la fois en mémoire et en stockage, est une décision que vous prenez dans votre implémentation, et donc vous devez prendre des mesures pour vous assurer que l'empreinte de code couplée à celle-ci la décision est petite - voir Parnas 1972 .
la source
Le GUID ou l' UUID sera très probablement unique en raison de la façon dont ils sont générés et ils fournissent un moyen sûr de garantir l'unicité sans avoir à communiquer avec une autorité centrale.
Avantages des GUID en tant que clé primaire:
Dans l'exemple que vous avez fourni:
La spécification du GUID avant l'heure d'insertion peut enregistrer un aller-retour dans la base de données lors de l'insertion d'enregistrements enfants successifs et vous permettre de les valider dans la même transaction.
Les inconvénients des GUID en tant que clé primaire:
Si votre application n'a pas besoin de partitionnement ou de clustering, il serait préférable de s'en tenir à des types de données plus petits et plus simples tels que int ou bigint.
De nombreuses bases de données ont leurs propres implémentations internes qui tentent d'atténuer les problèmes de stockage causés par les GUID et SQL Server a même une fonction newsequentialid pour aider à la commande des UUID permettant une meilleure utilisation des index et elles ont généralement de meilleures caractéristiques de performances.
De plus, du point de vue d'un testeur, d'un utilisateur ou d'un développeur travaillant avec l'application, l'utilisation d'un ID sur un GUID améliorera considérablement la communication. Imaginez avoir à lire un GUID sur un téléphone.
En fin de compte, à moins que le clustering à grande échelle ou l'URL d'obscurcissement ne soit une exigence, il est plus pragmatique de s'en tenir aux ID à incrémentation automatique.
la source
Je dirais non, n'utilisez pas les GUID comme clés primaires. Je suis en fait confronté à une telle base de données maintenant, et ils sont l'une des principales causes de problèmes de performances.
Les 12 octets supplémentaires s'additionnent rapidement; rappelez-vous, la plupart des PK seront des FK dans d'autres tables, et seulement trois FK dans une table vous avez maintenant 48 octets supplémentaires pour chaque ligne. Cela s'additionne dans la table et dans les index. Il s'additionne également dans les E / S disque. Ces 12 octets supplémentaires doivent être lus et écrits.
Et si vous n'utilisez pas de GUID séquentiels et que les PK sont regroupés (ce qui se produit par défaut), SQL devra de temps en temps déplacer des pages entières de données pour les presser davantage au bon endroit. Pour une base de données hautement transactionnelle avec beaucoup d'insertions, de mises à jour et de suppressions, les choses s'enlisent rapidement.
Si vous avez besoin d'une sorte d'identifiant unique pour la synchronisation ou quelque chose, ajoutez une colonne guid. Il suffit de ne pas en faire le PK.
la source
C'est de loin la raison la plus importante pour l'utilisation des GUID.
Le fait que vous puissiez créer un identifiant unique sans que votre code connaisse ou communique avec votre couche de persistance est un énorme avantage.
Vous pouvez être sûr que l'objet Personne que vous venez de générer sur votre serveur, téléphone pc, ordinateur portable, appareil hors ligne ou tout ce qui est unique sur tous vos serveurs partout dans le monde, quelle que soit sa distribution.
Vous pouvez le coller dans n'importe quel type de base de données rdb ou no-sql, fichier, l'envoyer à n'importe quel service Web ou le jeter immédiatement comme inédit
Non, vous n'obtiendrez jamais de collision.
Oui, les inserts peuvent être légèrement plus lents car il peut être nécessaire de manipuler l'index.
Oui, c'est plus grand qu'un int.
Je sais que beaucoup de gens sont très attachés aux pouces auto et c'est un sujet controversé avec les DBA
Mais je ne peux vraiment pas dire assez clairement à quel point les guides sont supérieurs. Vous devez utiliser des guides par défaut dans n'importe quelle application.
les incs automobiles ont de nombreux défauts
Vous utilisez une base de données distribuée sans SQL. Vous ne pouvez tout simplement pas parler à toutes les autres instances pour savoir quel est le prochain numéro.
Vous utilisez un système de file d'attente de messages. Les choses ont besoin d'identifiants avant de toucher la base de données
Vous créez plusieurs éléments et les modifiez avant d'enregistrer. Chacun a besoin d'un identifiant avant d'avoir touché la base de données
Vous souhaitez supprimer et réinsérer des lignes. Assurez-vous de ne pas compter vos identifiants automatiques et de manquer!
Vous ne voulez pas exposer le nombre de commandes que vous avez prises cette année à chaque utilisateur
Vous souhaitez déplacer les données anonymisées de la production vers les tests et conserver les relations intactes. Mais ne supprimez pas toutes les données de test existantes.
Vous souhaitez fusionner votre produit à locataire unique dans une base de données à locataires multiples, mais tout le monde a une commande 56.
Vous créez des objets persistants mais éphémères. (commandes incomplètes) encore une fois, n'utilisez pas toutes vos ints avec des trucs qui n'existent plus.
La liste est interminable et ce sont tous de vrais problèmes qui arrivent aux gens tout le temps. contrairement à manquer d'espace disque en raison de cols FK légèrement plus grands
Enfin, le problème majeur avec les pouces est que vous en manquez !!! ok en théorie vous ne le faites pas, il y a des charges. Mais en pratique, vous le faites parce que les gens ne les traitent pas comme des nombres aléatoires sans signification. ils font des choses comme
oh je ne veux pas que les clients pensent que nous sommes nouveaux. commencer à 10000
J'ai dû importer une charge de données donc j'ai juste augmenté la graine à 1 m pour que nous sachions ce qui est importé
nous avons besoin de catégories de données. chaque période commence au million suivant afin que nous puissions utiliser les premiers chiffres comme un nombre magique
J'ai supprimé et réimporté à nouveau toutes les données avec de nouveaux identifiants. Oui, même les journaux d'audit.
utiliser ce numéro, qui est une clé composite, comme id de cette autre chose
la source
C'est là que vous devez vous arrêter, juste là, et repenser.
La clé primaire de votre base de données ne doit JAMAIS avoir de sens commercial. Il devrait être dénué de sens par définition.
Ajoutez donc le GUID comme clé d'entreprise et une clé primaire normale (généralement un entier long) comme clé primaire de la base de données. Vous pouvez toujours mettre un index unique sur le GUID pour garantir l'unicité.
Cela parle bien sûr de la théorie des bases de données, mais c'est également une bonne pratique. J'ai traité des bases de données où les clés primaires avaient une signification commerciale (un client avait pensé à économiser certaines ressources de base de données en les utilisant comme numéros d'employé, numéros de client, etc. etc. par exemple) et cela causait toujours des problèmes.
la source
Utilisez toujours des clés primaires (PK) générées par base de données et auto-incrémentées.
Pourquoi utiliser l'incrémentation automatique au lieu de GUID / UUID?
Mais comment alors gérer les éclats, les clusters, etc.?
Un PK à 3 colonnes pour une table en cluster peut être ...
Mais qu'en est-il de ...?
Voyages multiples dans la base de données - La plupart des applications n'ont pas besoin d'identifier de manière unique un enregistrement en cours de création jusqu'à ce qu'il soit inséré dans la base de données, car ce thread / session / tout ce qui ne fonctionne que sur un à la fois. Si l'application a vraiment besoin de cette capacité, utilisez un PK temporaire généré par l'application qui n'est pas envoyé à la base de données . Laissez la base de données mettre ensuite son propre PK à incrémentation automatique sur la ligne lorsqu'elle est insérée. Les insertions utiliseront le PK temporaire, tandis que les mises à jour et les suppressions utiliseront le PK permanent attribué par la base de données.
Performances - Les ordinateurs peuvent traiter des entiers simples beaucoup plus rapidement que toute autre chose en raison du domaine beaucoup plus grand si possible des valeurs par élément dans un GUID (37) par rapport à un entier (10). N'oubliez pas non plus que chaque caractère d'un GUID doit d'abord être converti en nombre pour être manipulé par le CPU.
Mauvais usage courant des clés primaires Les PK n'ont qu'un seul but ... identifier de manière absolument unique une ligne dans une table. Tout le reste est une mauvaise utilisation trop courante.
Détection des enregistrements manquants
Tri
la source
Comme tout, il y a des avantages et des inconvénients à le faire:
Le bon:
Vos clés ont toujours la même longueur (les très grandes bases de données peuvent avoir de très grandes clés)
L'unicité est à peu près garantie - même lorsque vous les générez à partir d'un système distinct et / ou que vous n'avez pas lu le dernier ID de la base de données
Le mauvais:
Comme mentionné ci-dessus - des index et un magasin de données plus importants.
Vous ne pouvez pas commander par ID, vous devez commander par autre chose. Plus d'index, probablement moins efficaces.
Ils sont moins lisibles par l'homme. Les entiers sont généralement plus faciles à analyser, à mémoriser et à taper pour les gens. L'utilisation de GUID comme ID dans des clauses WHERE sur plusieurs tables jointes peut faire fondre votre tête.
Comme tout, utilisez-les le cas échéant, ne soyez pas dogmatique - dans de nombreuses situations, les entiers à incrémentation automatique sont meilleurs, parfois les GUID sont excellents.
la source
Oui, vous pouvez utiliser le GUID comme clé primaire. L'inconvénient est la taille et la fragmentation rapide de l'indice.
Sauf si vous avez besoin d'unicité entre les bases de données (par exemple un cluster), l'entier est préférable.
la source
Voici mon point de vue sur ce problème - la solution est à mi-chemin entre le GUID et les valeurs int, en prenant le meilleur des deux.
La classe génère une valeur Id pseudo aléatoire (mais augmentant avec le temps), qui est similaire à un GUID Comb .
Le principal avantage est qu'il permet de générer des valeurs Id sur le client, plutôt que d'utiliser des valeurs d'auto-incrémentation générées sur le serveur (ce qui nécessite un aller-retour) avec un risque presque nul de valeurs dupliquées.
Les valeurs générées n'utilisent que 8 octets au lieu de 16 pour un GUID, et ne dépendent pas d'un ordre de tri de base de données spécifique (par exemple Sql Server for GUIDs ). Les valeurs pourraient être développées pour utiliser toute la longue plage non signée, mais cela entraînerait des problèmes avec toute base de données ou autre référentiel de données qui ne possède que des types entiers signés.
la source