Guid vs INT - Quel est le meilleur en tant que clé primaire?

97

J'ai lu autour des raisons d'utiliser ou non Guidet int.

intest plus petit, plus rapide, facile à retenir, conserve une séquence chronologique. Et pour ce Guidqui est du seul avantage que j’ai trouvé, c’est que c’est unique. Dans quel cas un Guidserait mieux que intet pourquoi?

D'après ce que j'ai vu, intil n'y a aucun défaut, si ce n'est la limite du nombre, qui dans de nombreux cas est sans importance.

Pourquoi exactement a été Guidcréé? En fait, je pense que cela a un but autre que celui de servir de clé primaire d'un simple tableau. (Un exemple d'application réelle utilisant Guidquelque chose?)

(Guid = UniqueIdentifier) ​​sur SQL Server

BrunoLM
la source
1
Plutôt que clé primaire , je pense que vous voulez dire clé de substitution, c'est-à-dire une clé qui n'est pas la clé naturelle (cette dernière étant la clé que nous utilisons dans le monde réel). Peut-être que vous voulez dire index clusterisé.
jourquand le
Rappelez-vous également la différence entre (primaire) KEY et INDEX.
Allan S. Hansen
1
Également discuté sur l'OS: stackoverflow.com/questions/11033435/…
Jon of All Trades
2
" intn'a de défaut que par la limite en nombre, qui dans de nombreux cas est sans importance.": en fait, dans ce contexte INT vs GUID, la limite supérieure d'un 32 bits signé INTest totalement sans importance étant donné que la limite supérieure d'un signe 64 bits BIGINTest bien au-delà de presque toutes les utilisations (encore plus si vous commencez à numéroter à la limite inférieure; il en va de même INT) et qu’il a toujours la moitié de la taille d’un GUID (8 octets au lieu de 16) et séquentiel.
Solomon Rutzky

Réponses:

89

Cela a été demandé dans Stack Overflow ici et ici .

Le post de Jeff explique beaucoup sur les avantages et les inconvénients de l'utilisation du GUID.

GUID Pour

  • Unique sur chaque table, chaque base de données et chaque serveur
  • Permet de fusionner facilement des enregistrements de différentes bases de données
  • Permet une distribution facile des bases de données sur plusieurs serveurs
  • Vous pouvez générer des identifiants n'importe où, au lieu d'avoir à aller à la base de données
  • La plupart des scénarios de réplication nécessitent quand même des colonnes GUID

GUID Contre

  • C'est quatre fois plus grand que la valeur d'index classique à 4 octets; cela peut avoir de graves conséquences sur les performances et le stockage si vous ne faites pas attention
  • Encombrant à déboguer ( where userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • Les GUID générés doivent être partiellement séquentiels pour newsequentialid()optimiser les performances ( sur SQL Server 2005+, par exemple) et pour permettre l'utilisation d'index en cluster.

Si vous êtes certain des performances et que vous ne prévoyez pas de répliquer ou de fusionner des enregistrements, utilisez int-le et définissez-le comme une incrémentation automatique ( graine d'identité dans SQL Server ).

CoderHawk
la source
20
Un autre inconvénient de l'approche GUID est que vous ne pouvez pas l'utiliser comme identifiant pour votre utilisateur final. Vous attendez-vous vraiment de vos utilisateurs qu'ils vous disent au téléphone qu'ils ont un problème avec la commande "BAE7DF4-DDF-3RG-5TY3E3RF456AS10"? :)
Brann
3
Si vous n'utilisez pas d'instructions séquentielles et que votre clé primaire est en cluster (le SQL Server par défaut), toutes vos insertions de données seront dispersées de manière aléatoire dans le tableau, ce qui entraînera une fragmentation massive de vos données. Cela suppose que les données seraient normalement insérées dans un ordre quelconque, tel que chronologique.
datagod
6
Les instructions séquentielles sont uniquement séquentielles jusqu'au redémarrage de l'instance SQL. Ensuite, la première valeur sera probablement inférieure à la précédente en raison de la manière dont la valeur racine est générée, ce qui provoque toutes sortes de problèmes.
mrdenny
20
@Brann Idéalement, vos valeurs de PK ne devraient pas être communiquées aux utilisateurs finaux. Je sais que c'est assez courant de le faire et c'est quelque chose que j'ai moi-même fait par le passé avant d'apprendre à ne pas le faire. Mais comme cela ne devrait pas être fait, cette raison particulière de préférer INT au GUID n'est pas valide.
Solomon Rutzky
2
@ChadKuehn Choisir UNIQUEIDENTIFIERplus INTparce INTque sa limite supérieure est un raisonnement plutôt médiocre, car être illimité, bien que vrai, ne constitue pas un avantage pratique . Vous pouvez facilement doubler la capacité réelle d'un INTen le démarrant à la limite inférieure (-2,14 milliards) au lieu de 1. Sinon, si les 4,3 milliards ne suffisent pas, commencez avec une valeur de BIGINTseulement 8 octets. comparé à 16 pour le GUID, et il est séquentiel.
Solomon Rutzky
18

Si vous synchronisez vos données avec une source externe, un GUID persistant peut être bien meilleur. Un exemple rapide d'utilisation d'un GUID est un outil envoyé au client pour analyser son réseau et effectuer certaines classes de détection automatique, stocker les enregistrements trouvés, puis tous les enregistrements du client sont intégrés dans une base de données centrale. retour sur notre fin. Si nous utilisions un entier, nous aurions 7 398 "1", et il serait beaucoup plus difficile de savoir lequel "1" était lequel.

TML
la source
3
Les GUID sont vraiment bons comme identifiants externes, et je garderais un index non-cluster de cela comme "clé externe" Je garderais toujours un int comme "clé interne" qui est la base des relations d'index cluster et de clé étrangère. Si quelque chose doit traverser une frontière architecturale (par exemple, communiquer avec une autre application), j'apprécie vraiment d'avoir quelque chose qui ne peut pas être mélangé.
Greg
15

J'ai utilisé une approche hybride avec succès. Les tables contiennent à la fois une idcolonne d' entier de clé primaire à incrémentation automatique ET une guidcolonne. Le guidpeut être utilisé selon les besoins pour identifier globalement la ligne de manière unique et idpeut être utilisé pour les requêtes, le tri et l'identification humaine de la ligne.

rmirabelle
la source
3
Quelle valeur le GUID donne-t-il si le nombre idsuffisant est déjà suffisant pour permettre aux humains d'identifier une ligne?
Martin Smith
6
L'identifiant identifie la ligne dans cette table. Le GUID (du moins en théorie) identifie cette ligne n'importe où dans l'univers connu. Dans mon projet, les mobiles Android possèdent chacun une copie structurellement identique de la table sur une base de données SQLite locale. La ligne et son GUID sont chacun générés sur Android. Ensuite, lorsque Android est synchronisé sur la base de données principale, sa ligne locale est écrite dans la table principale sans crainte de conflit avec les lignes créées à partir de n’importe quel autre mobile Android.
rmirabelle
2
@ MartinSmith J'ai utilisé cette approche moi-même et cela fonctionne assez bien. Le GUID est simplement une clé alternative, avec un index non clusterisé, et est transmis à partir de l'application, mais réside uniquement dans la table primaire. Toutes les tables liées sont liées via la INTPK. Je trouve étrange que cette approche ne soit pas beaucoup plus commune étant donné que c’est le meilleur des deux mondes. Il semble que la plupart des gens préfèrent simplement résoudre des problèmes dans des termes très absolutistes, sans se rendre compte que la PK n'a pas besoin d'être un GUID pour que l'application puisse toujours utiliser des GUID pour une unicité et / ou une portabilité globales.
Solomon Rutzky
1
@rmirabelle J'avais réfléchi à cette approche et j'hésitais, mais votre réponse m'a convaincu. En gros, je suis dans une situation où j'ai besoin d'un identifiant unique pour un élément de travail (qui peut entrer sur le réseau à partir de n'importe où), mais je ne souhaite pas aller d'abord dans la base de données. Les GUID sont une bonne solution pour cela, mais j'imagine que les JOIN vont devenir beaucoup plus lents si je n'ai pas de clé en cluster séquentielle.
easuter
1
@easuter Je suis d'accord pour ne pas ajouter de champs d'ID "juste pour le plaisir de le faire", comme dans les tables "pont" plusieurs à plusieurs, dans lesquelles la PK doit être un composite des deux FK liés. Mais ici, ce n’est pas un compromis, car le champ ID n’est pas simplement pour l’intérêt de celui-ci. Permettre au système de fonctionner efficacement est assez important ;-). ET, je dirais que dans votre cas, puisque les GUID sont générés à l'extérieur, ceux-ci ne sont pas garantis comme étant uniques, même s'ils le sont de façon pragmatique. Mais la responsabilité de l'intégrité des données est une raison suffisante pour que le GUID soit une clé alternative et que l'ID soit une clé PK dans votre cas :)
Solomon Rutzky
1

Certaines pratiques recommandées mentionnent encore que vous devez utiliser un type de données qui héberge avec le moins de mémoire possible l’ensemble des valeurs que vous allez utiliser. Par exemple, si vous l'utilisez pour stocker le nombre d'employeurs dans une petite entreprise et que vous n'atteignez probablement pas 100, personne ne suggérera alors d'utiliser une valeur bigint alors que int (même de petite taille) ferait l'affaire.

Bien entendu, l’inconvénient est que «Dites non à l’évolutivité!


De plus, je sais que ce n'est pas totalement lié, mais il y a un autre facteur à ce sujet. Lorsque cela n’est pas excessif, j’essaie généralement de recommander l’utilisation d’une clé primaire non générée automatiquement, si cela a du sens. Par exemple, si vous enregistrez les informations du conducteur, ne créez pas une nouvelle colonne générée automatiquement pour "ID", utilisez simplement le numéro de licence.

Je sais que cela semble vraiment évident, mais je vois cela être oublié assez souvent.

Pour le contexte: cette partie de la réponse a été abordée à partir d’une approche théorique des données, dans laquelle vous souhaitez que votre PC soit l’identificateur de données unique d’un enregistrement. La plupart du temps, nous créons ceux qui existent déjà, d'où la réponse précédente.

Cependant, il est très rare que vous puissiez avoir un contrôle étroit sur ces points de données et, par conséquent, vous devrez peut-être apporter des corrections ou des ajustements. Vous ne pouvez pas faire cela avec des clés primaires (enfin, vous le pouvez, mais cela peut être pénible).

Merci @VahiD pour les éclaircissements.

Alpha
la source
L'utilisation de clés primaires significatives n'est pas du tout recommandée. Envisagez le scénario ci-dessous. Une personne a saisi un numéro de licence erroné et vous avez utilisé cet ID dans des tables 3-4 en tant que clé étrangère. Comment corrigez-vous cette erreur? éditer simplement le numéro de licence ne pourrait pas suffire dans ce cas.
VahiD
1
C'est marrant: j'ai lu votre commentaire et je me suis dit "oui, bien sûr", puis je suis revenu pour lire ma réponse et j'ai pensé "ai-je dit cela"? C'est drôle comme les choses changent en quelques années. Je venais probablement d'un contexte plus théorique, mais à moins que vous ne le contrôliez de près (rarement), cela n'apporte pas beaucoup d'avantages. Je vais mettre à jour la réponse.
Alpha
Vote positif pour le développement dans les années :)
VahiD
1

L'utilisation d'identifiants d'incrémentation automatique peut entraîner la fuite d'informations sur votre activité. Si vous exploitez un magasin et utilisez order_idpour identifier publiquement un achat, tout le monde peut connaître votre nombre mensuel de ventes à l'aide d'une simple arithmétique.

Golopot
la source
0

Une autre chose avec la façon dont les GUID sont générés. mrdenny a correctement fait remarquer que même si newsequentialid () est utilisé, le redémarrage des instances fait en sorte que les nouvelles valeurs commencent par les "trous" laissés dans le traitement précédent. Une autre chose qui affecte les GUID "séquentiels" est la carte réseau. Si je me souviens bien, l'UID de la carte réseau est utilisé dans le cadre de l'algorithme GUID. Si une carte réseau est remplacée, rien ne garantit que l'UID sera une valeur plus élevée pour conserver l'aspect séquentiel des choses. Je ne sais pas non plus comment plusieurs cartes d'interface réseau peuvent affecter l'affectation de valeurs à l'aide de l'algorithme.

Juste une pensée et j'espère que je me souviens bien. Passez une bonne journée!

bobo8734
la source
2
Bienvenue aux administrateurs de base de données, bobo8734. Pourriez-vous trouver des sources pour ces commentaires? Si vous n'êtes pas sûr d'eux, ils feraient peut-être mieux de servir de commentaires (lorsque vous avez le représentant), plutôt que de répondre de manière autonome.
LowlyDBA
-6

Utilise les deux

Utilisez int / Bigint pour la clé primaire car il est facile à gérer et à utiliser comme relation de clé étrangère.

Mais lier une colonne au GUID afin que chaque ligne ait également une colonne unique

Abdul Hannan Ijaz
la source
2
Expliquer votre raisonnement derrière cette suggestion ne ferait de mal à personne, j'en suis sûr.
Andriy M
Le GUID, composé de 36 caractères, sera difficile à lire si vous recherchez un cas spécifique.
Abdul Hannan Ijaz
1
D'accord, mais cela n'explique pas vraiment pourquoi le PO devrait utiliser les deux intet guid, comme vous le suggérez dans votre réponse. Et puis, je ne parlais pas d'expliquer votre suggestion juste à moi - je voulais simplement mettre à jour votre réponse . Au fait, savez-vous qu'un autre répondant a déjà suggéré la même chose (plus ou moins) à vous ?
Andriy M
Ouais je voulais dire la même chose .. cool BTW :)
Abdul Hannan Ijaz