Dans une discussion assez animée dans mon équipe, j'ai été amené à penser à ce que la plupart des gens aiment comme clés primaires. Nous avions les groupes suivants-
Quelle est la meilleure approche pour les PK? Ce serait génial si vous pouviez justifier votre opinion. Existe-t-il une meilleure approche que ci-dessus?
EDIT: Quelqu'un a-t-il un échantillon/algorithme simple pour générer des identificateurs lisibles par l'homme pour les lignes qui évoluent bien?
Si vous souhaitez effectuer une synchronisation entre des bases de données avec des applications parfois connectées, vous devez utiliser des GUID pour vos clés primaires. C'est une sorte de douleur pour le débogage, donc en dehors de ce cas, j'ai tendance à m'en tenir à l'auto-incrémentation.
Les entiers à auto-incrémentation doivent être votre valeur par défaut, et pas leur utilisation doit être justifiée.
Je ne vois pas de réponse qui souligne (ce que je considère comme) le point vraiment fondamental - à savoir, qu'une clé primaire est ce qui garantit que vous n'obtiendrez pas deux entrées dans le tableau pour la même entité du monde réel (comme modélisé dans la base de données). Cette observation permet d'établir ce qui est bon et ce qui est mauvais choix pour la clé primaire.
Par exemple, dans un tableau de noms et de codes d'état (US), le nom ou le code peut être la clé primaire - ils constituent deux clés candidates différentes, et l'une d'entre elles (normalement la plus courte - le code) est choisie comme clé primaire. Dans la théorie des dépendances fonctionnelles (et des dépendances de jointure - 1NF à 5NF - ce sont les clés candidates qui sont cruciales plutôt qu'une clé primaire.
Pour un contre-exemple, les noms humains font généralement un mauvais choix pour la clé primaire. Il y a beaucoup de gens qui s'appellent "John Smith" ou d'autres noms similaires; même en tenant compte des prénoms (rappelez-vous: tout le monde n'en a pas - par exemple, je n'en ai pas), il y a beaucoup de possibilités de duplication. Par conséquent, les gens n'utilisent pas de noms comme clés primaires. Ils inventent des clés artificielles telles que le numéro de sécurité sociale (SSN) ou le numéro d'employé et les utilisent pour désigner l'individu.
Une clé primaire idéale est courte, unique, mémorable et naturelle. Parmi ces caractéristiques, l'unicité est obligatoire; les autres doivent fléchir compte tenu des contraintes des données réelles.
Par conséquent, lorsqu'il s'agit de déterminer la clé primaire d'une table donnée, vous devez regarder ce que cette table représente. Quel ensemble ou ensembles de valeurs de colonne dans le tableau identifie de façon unique chaque ligne du tableau? Ce sont les clés candidates. Maintenant, si chaque clé candidate se compose de 4 ou 5 colonnes, vous pourriez décider qu'elles sont trop maladroites pour faire une bonne clé primaire (principalement pour des raisons de brièveté). Dans ces circonstances, vous pouvez introduire une clé de substitution - un nombre généré artificiellement. Très souvent (mais pas toujours) un simple entier 32 bits est suffisant pour la clé de substitution. Vous désignez ensuite cette clé de substitution comme clé primaire.
Cependant, vous devez toujours vous assurer que les autres clés candidates (car la clé de substitution est également une clé candidate, ainsi que la clé primaire choisie) sont toutes conservées comme identifiant unique - normalement en plaçant une contrainte unique sur ces ensembles de colonnes.
Parfois, les gens ont du mal à identifier ce qui rend une ligne unique, mais il devrait y avoir quelque chose à faire, car la simple répétition d'une information ne la rend plus vraie. Et si vous ne faites pas attention et que vous obtenez deux (ou plus) lignes censées stocker les mêmes informations, et que vous devez ensuite mettre à jour les informations, il y a un danger (surtout si vous utilisez des curseurs) que vous ne mettiez à jour qu'une seule ligne plutôt que chaque ligne, donc les lignes ne sont pas synchronisées et personne ne sait quelle ligne contient les informations correctes.
C'est une vision assez dure, à certains égards.
Je n'ai aucun problème particulier à utiliser un GUID quand ils sont nécessaires, mais ils ont tendance à être gros (comme dans 16 à 64 octets), et ils sont utilisés trop souvent. Très souvent, une valeur de 4 octets parfaitement suffisante suffit. L'utilisation d'un GUID où une valeur de 4 octets suffirait à gaspiller de l'espace disque, et ralentit même l'accès indexé aux données car il y a moins de valeurs par page d'index, donc l'index sera plus profond et plus de pages doivent être lues pour accéder aux informations.
Ce n'est qu'une question religieuse parce que les gens cherchent une bonne réponse universelle. Le fait que votre équipe et ce fil SO montrent tant de désaccord devrait être un indice qu'il y a de bonnes raisons d'utiliser toutes les solutions que vous décrivez, dans différentes circonstances.
state
(CA, TX, NY), vous pouvez tout aussi bien utiliser une clé naturelle char(2)
au lieu d'un entier.id
" lorsqu'une clé composée parfaitement bonne existe (cela est particulièrement vrai dans les tableaux plusieurs-à-plusieurs). Un mandat pour une clé à trois colonnes dans chaque table est un non-sens absolu.J'aime le blog du programmeur de base de données comme source pour ce genre d'informations.
3 colonnes pour une clé primaire? Je dirais que les colonnes devraient avoir des contraintes uniques appropriées comme l'exigent les règles métier, mais j'aurais toujours une clé de substitution distincte. Les clés composées signifient que la logique métier entre dans la clé. Si la logique change, tout votre schéma est vissé.
J'aime le mien unique.
Je vais toujours avec la clé de substitution. Une clé de substitution (généralement une colonne d'identité, une auto-incrémentation ou un GUID) est une clé dans laquelle la clé n'est pas présente dans les données elles-mêmes. Une clé naturelle, en revanche, est une clé qui, à elle seule, identifie de manière unique la ligne. Autant que je sache dans la vie, il n'y a pratiquement pas de vrais clés naturelles. Même des choses comme SSN aux États-Unis ne sont pas une clé naturelle. Les clés primaires composites sont une catastrophe qui attend de se produire. Vous ne pouvez modifier aucune de ces données (ce qui est l'inconvénient majeur de toute clé naturelle, composite ou non), mais pire, c'est qu'avec une clé composite, vous devez maintenant perpétuer ces données de clé dans chaque table associée. Quel gaspillage géant.
Maintenant, pour la sélection de la clé de substitution, je m'en tiens aux colonnes d'identité (je travaille principalement dans MS SQL Server). Les GUID sont trop grands et Microsoft recommande contre de les utiliser comme PK. Si vous avez plusieurs serveurs, tout ce que vous avez à faire est de faire l'incrémentation de 10 ou 20 ou tout ce que vous pensez le nombre maximum de serveurs que vous aurez jamais besoin de synchroniser/développer, et juste augmenter la valeur de départ pour chaque table sur chaque serveur suivant et vous n'aurez jamais de collision de données.
Bien sûr, en raison de l'incrément, je fais de la colonne d'identité un BigInt (autrement connu comme un long [64 bits]).
En faisant un peu de calcul, même si vous effectuez l'incrémentation de 100, vous pouvez toujours avoir 92,233,720,368,547,758 (> 92 quadrillions) de lignes dans votre tableau.
Je pense que l'utilisation du mot "primaire", dans l'expression "clé primaire" est dans un sens réel, trompeuse.
Tout d'abord, utilisez la définition qu'une "clé" est un attribut ou un ensemble d'attributs qui doit être unique dans la table,
Ensuite, avoir une clé sert à plusieurs fins souvent incompatibles.
Pour augmenter la performance des requêtes qui doivent localiser rapidement un enregistrement/une ligne spécifique dans le tableau.
Pour garantir la cohérence des données en empêchant l'insertion de lignes en double représentant la même entité logique dans la table. (Ceci est souvent appelé une clé "naturelle" et doit être constitué d'attributs de table (entité) qui sont relativement invariants.)
De toute évidence, toute clé non significative et non naturelle (comme un GUID ou un entier généré automatiquement) est totalement incapable de satisfaire # 4.
Mais souvent, avec de nombreuses (la plupart) des tables, une clé totalement naturelle qui peut fournir # 4 sera souvent composée de plusieurs attributs et sera excessivement large, ou si large que son utilisation aux fins # 1, # 2 ou # 3 entraînera inacceptable conséquencecs de performance.
La réponse est simple. Utilise les deux. Utilisez une clé intégrale à génération automatique simple pour toutes les jointures et tous les FK dans d'autres tables enfants, mais assurez-vous que chaque table qui nécessite la cohérence des données (très peu de tables n'en ont pas) possède une clé unique naturelle alternative qui empêchera l'insertion de lignes de données incohérentes. .. De plus, si vous avez toujours les deux, alors toutes les objections contre l'utilisation d'une clé naturelle (et si elle change? Je dois changer chaque endroit où elle est référencée comme un FK) deviennent sans objet, car vous ne l'utilisez pas pour cela. .. Vous ne l'utilisez que dans la seule table où il s'agit d'un PK, pour éviter les données en double incohérentes ...
En ce qui concerne les GUID, soyez très prudent en les utilisant, car l'utilisation de guides dans un index peut ralentir la fragmentation de l'index. Les algorithmes les plus courants utilisés pour les créer placent la partie "aléatoire" du guid dans les positions de bits les plus significatives ... Cela augmente la nécessité d'une défragmentation/réindexation d'index régulière à mesure que de nouvelles lignes sont ajoutées.
Légèrement hors sujet, mais je me sens obligé de faire sonner avec ...
Si votre clé primaire est un GUID, ne pas en faire un index clusterisé. Étant donné que les GUID ne sont pas séquentiels, les données seront réorganisées sur le disque pendant presque chaque insertion. (Beurk.) Si vous utilisez des GUID comme clés primaires, ils doivent être des index non clusterisés.
Une chose que vous ne devriez jamais faire est d'utiliser une clé intelligente. C'est une clé où les informations sur l'enregistrement sont codées dans la clé elle-même, et cela finira par vous mordre.
J'ai travaillé un seul endroit, où la clé primaire était l'ID du compte, qui était une combinaison de lettres et de chiffres. Je ne me souviens pas de détails, mais, par exemple, ces comptes qui étaient d'un certain type, seraient dans la plage 600, et d'un autre type, a commencé avec 400. C'était super, jusqu'à ce que ce client décide de demander les deux types de travaux. Ou changé le type de travail qu'ils faisaient.
Un autre endroit, a utilisé l'emplacement dans l'arborescence comme clé primaire pour les enregistrements. Il y aurait donc des enregistrements comme les suivants.
Cat1.subcatA.record1
Cat1.subcatA.record2
Cat1.subcatB.record1
Cat2.subcatA.record1
Bien sûr, la première chose que les clients voulaient était un moyen de déplacer les éléments dans l'arbre. L'ensemble des logiciels est mort avant que cela ne se produise.
S'il vous plaît, s'il vous plaît, s'il vous plaît, si vous écrivez du code que je dois maintenir, n'utilisez pas de clé intelligente!
Je suis fan de l'incrémentation automatique comme clé primaire. Je sais au fond de moi que c'est une dérobade, mais il est si facile de trier les données en fonction de leur date d'ajout (ORDER BY ID DESC, par exemple).
3 colonnes semblent terriblement difficiles à analyser humainement.
Et c'est le compromis - de combien de capacité relationnelle avez-vous besoin, par rapport à rendre CE TABLEAU ICI compréhensible pour un humain qui l'interroge (par rapport à la procédure stockée ou à l'interface programmatique).
l'auto-incrémentation est pour nous les humains. :-(
En général, cela dépend.
Personnellement, j'aime les entiers à auto-incrémentation.
Mais, une chose que je peux vous dire, c'est de ne jamais faire confiance aux données d'autres sources comme clé. Je le jure, chaque fois que je l'ai fait, ça revient me mordre. Eh bien, plus jamais!
Il devrait y avoir au moins 3 colonnes qui composent la clé primaire.
Je ne comprends pas ça.
Parlez-vous d'une "clé naturelle", par exemple "nom et date de naissance"? Une clé naturelle peut être idéale si elle existe, mais la plupart des candidats pour une clé naturelle ne sont pas uniques (plusieurs personnes avec le même nom) ou pas constants (quelqu'un peut changer de nom).
Int/BigInt dont l'auto-incrémentation est une clé primaire suffisamment bonne.
Je préfère Guid. Un problème potentiel avec l'auto-incrémentation est que la valeur (par exemple "ID de commande") est attribuée par l'instance de base de données (par exemple par la "base de données de vente") ... ce qui ne fonctionnera pas entièrement (au lieu de cela, vous commencez à avoir besoin de clés composées) si vous avez toujours besoin de fusionner des données créées par plusieurs instances de base de données (par exemple, de plusieurs bureaux de vente ayant chacun leur propre base de données).
RE GUID's
Attention si cela va être vraiment VRAIMENT VRAIMENT VRAIMENT grande base de données, beaucoup de charge et un accès rapide.
Lors de mon dernier travail, où nous avions des bases de données de 100 à 500 millions d'enregistrements, nos gars de base de données se sont fortement opposés aux GUID et à un nombre décimal de taille appropriée. Ils ont estimé que (sous Oracle) la différence de taille dans le stockage interne pour une chaîne Guid - par rapport à une valeur décimale ferait une différence très notable dans les recherches. (Touches plus grandes = arbres plus profonds à traverser)
La nature aléatoire des GUID réduit également considérablement le facteur de remplissage des pages d'index, ce qui augmente considérablement le déchirement et les E/S du disque.
Colonnes d'incrémentation automatique. Je suis capable de faire fonctionner mon code de façon transparente avec SQL Server ou Oracle, l'un utilisant l'identité l'autre utilisant des séquences via mon DAL, et je ne pourrais pas être plus heureux. Je suis d'accord, les GUID sont parfois nécessaires si vous effectuez une réplication ou envoyez des données pour les recevoir plus tard après le traitement.
J'ai toujours utilisé une clé de substitution - un entier à incrémentation automatique appelé "id". Je peux voir de nombreuses raisons de le faire même lorsqu'une autre option est évidente:
... et aucune raison raisonnable de ne pas:
des raisons sensées contre lesquelles je n'ai pas pensé ou que je n'ai pas encore rencontrées sont toujours les bienvenues ...
J'aime les clés naturelles, chaque fois que je peux leur faire confiance. Je suis prêt à payer un petit prix de performance pour utiliser des clés qui ont du sens pour les experts en la matière.
Pour les tableaux qui décrivent des entités, il devrait y avoir une clé naturelle simple qui identifie les instances individuelles de la même manière que le sujet. Si le sujet n'a pas d'identifiants fiables pour l'une des entités, je vais recourir à une clé de substitution.
Pour les tables qui décrivent des relations, j'utilise une clé composée, où chaque composant fait référence à une entité qui participe à la relation, et donc une ligne dans une table d'entités. Encore une fois, les performances pour l'utilisation d'une clé composée sont généralement minimes.
Comme d'autres l'ont souligné, le terme "clé primaire" est un peu trompeur. Dans le modèle de données relationnelles, le terme utilisé est "clés candidates". Il peut y avoir plusieurs clés candidates pour une même table. Logiquement, chacun est aussi bon qu'un autre. Choisir l'un d'eux comme "principal" et faire toutes les références via cette clé est simplement un choix que le concepteur peut faire.
Seulement un peu pertinent, mais une chose que j'ai commencé à faire récemment quand j'ai de petites tables de classification (essentiellement celles qui représenteraient les ENUM dans le code) est que je ferai de la clé primaire un char (3) ou char (4). Ensuite, je rend ces clés primaires représentatives de la valeur de recherche.
Par exemple, j'ai un système de devis pour nos agents commerciaux internes. Nous avons des "catégories de coûts" auxquelles chaque élément de campagne de devis est affecté ... J'ai donc une table de recherche de type appelée "tCostCategories", où la clé primaire est "MTL", "SVC", "TRV", "TAX", "ODC". D'autres colonnes de la table de recherche contiennent plus de détails, telles que les significations anglaises normales des codes, "Matériel", "Service", "Voyage", "Taxes", "Autres coûts directs", etc.
C'est vraiment bien car il n'utilise pas plus d'espace qu'un int, et lorsque vous regardez les données source, vous n'avez pas besoin de lier la table de recherche pour savoir quelle est la valeur. Par exemple, une ligne de devis peut ressembler à:
1 Numéro de pièce 40 $ MTL
2 OtherPartNumber 29,99 $ SVC
3 Numéro de référence2 150 $ TRV
Il est beaucoup plus facile d'utiliser un int pour représenter les catégories, puis de lier 1, 2, 3 sur toutes les lignes - vous avez les données juste devant vous, et les performances ne semblent pas du tout affectées (pas que je '' ve vraiment testé.)
En ce qui concerne la vraie question ... J'aime les identifiants uniques RowGUID. Je ne suis pas à 100% là-dessus, mais toutes les lignes n'ont-elles pas de RowGuid internes de toute façon ?? Si c'est le cas, l'utilisation du RowGuid prendrait en fait moins d'espace que les entiers (ou toute autre chose d'ailleurs). Tout ce que je sais, c'est que si c'est assez bon pour que M $ utilise dans GreatPlains, c'est assez bon pour moi. (Dois-je esquiver ??)
Oh, encore une raison pour laquelle j'utilise des GUID - j'utilise une structure de données hiérarchique. C'est-à-dire que j'ai une table 'Company' et une table 'Vendor' pour lesquelles les clés primaires correspondent. Mais j'ai aussi une table "Fabricant" qui "hérite" également de la société. Les champs communs aux Vendeurs et Fabricants n'apparaissent pas dans ces tableaux - ils apparaissent dans Société. Dans cette configuration, l'utilisation d'int est beaucoup plus pénible que Guids. À tout le moins, vous ne pouvez pas utiliser de clés primaires d'identité.
C'est un classique "ça dépend". Il n'y a pas de bonne réponse pour chaque projet. J'aime différentes choses pour différentes situations. Cela dépend si j'utilise un ORM et ce qu'il prend en charge. Cela dépend de l'architecture globale (distribuée ou non, etc.). Choisissez simplement celui qui, selon vous, fonctionnera et passez à la discussion sur les tabulations et les espaces.
J'ai tendance à utiliser l'option # 1 ou # 3 en fonction de la taille, du nombre de personnes qui se connectent et selon qu'il s'agit d'une situation de serveur de bases de données multiples ou non.
L'option n ° 2 n'a pas beaucoup de sens pour moi. Si l'un des trois n'est pas suffisant pour identifier un enregistrement unique, il est possible (sans passer par des opérations supplémentaires) que deux enregistrements aient deux enregistrements avec les mêmes valeurs dans les trois colonnes. Si vous souhaitez appliquer l'unicité à n'importe quelle combinaison des trois, ajoutez simplement un index pour eux.
Guids.period.
Dans le cas où vous devez évoluer ou vous devez attribuer la clé primaire par d'autres moyens, ils seront votre ami. Vous pouvez ajouter des index pour tout le reste.
mettre à jour pour clarifier ma déclaration.
J'ai travaillé sur différents types de sites. Des petites offres de serveur unique aux grandes offres soutenues par plusieurs serveurs DB et Web. Il y a certainement eu des applications qui auraient été très bien avec des incréments à incrémentation automatique comme clés primaires. Cependant, ceux-ci ne correspondent pas au modèle de la façon dont je fais les choses.
Lorsque vous utilisez un GUID vous pouvez générer l'ID n'importe où. Il peut être généré par un serveur distant, votre application Web, dans la base de données elle-même ou même dans plusieurs bases de données dans une situation multimaître.
D'un autre côté, un INT incrémenté automatiquement ne peut être généré en toute sécurité que dans la base de données primaire. Encore une fois, cela pourrait être correct si vous avez une application qui sera intimement liée à ce serveur de sauvegarde et que la mise à l'échelle n'est pas quelque chose qui vous préoccupe.
Bien sûr, l'utilisation des GUID signifie que vous devez avoir des processus de réindexation nocturnes. Cependant, si vous utilisez autre chose qu'un INT incrémenté automatiquement, vous devez le faire quand même. Heck, même avec un INT comme principal, il est probable que vous ayez d'autres index qui doivent être régénérés pour faire face à la fragmentation. Par conséquent, l'utilisation des GUID n'ajoute pas exactement un autre problème, car ces tâches doivent être effectuées malgré tout.
Si vous jetez un œil aux plus grandes applications, vous remarquerez quelque chose d'important: elles utilisent toutes des GUID encodés en Base64 comme clés. La raison en est simple, l'utilisation des GUID vous permet de mettre à l'échelle out facilement alors qu'il peut y avoir beaucoup de cerceaux à franchir lorsque vous tentez de mettre à l'échelle les INT.
Notre dernière application traverse une période d'inserts lourds qui dure environ un mois. Après cela, 90 +% des requêtes sont toutes sélectionnées pour les rapports. Pour augmenter la capacité, je peux faire apparaître des serveurs DB supplémentaires pendant cette grande période d'insertion; et plus tard, fusionnez-les facilement en une seule base de données pour les rapports. Tenter de le faire avec des INT serait un cauchemar absolu.
Franchement, chaque fois que vous mettez en cluster une base de données ou que vous répliquez la configuration, le serveur de base de données va de toute façon exiger que vous ayez des GUID sur la table. Donc, si vous pensez que votre système a besoin de croître, choisissez celui qui vous convient.
Je n'ai utilisé qu'un auto-increment int ou un GUID. 99% du temps, j'utilise l'incrémentation automatique int. C'est juste ce qu'on m'a appris à utiliser lorsque j'ai découvert les bases de données et je n'ai jamais rencontré de raison de ne pas les utiliser (bien que je sache pourquoi un GUID serait mieux).
J'aime les incréments d'incrémentation automatique car cela aide à la lisibilité. Par exemple, je peux dire "jetez un œil à l'enregistrement 129383" et il est assez facile pour quelqu'un d'entrer et de le trouver. Avec un GUID c'est presque impossible à faire.
Après une réponse définitionnelle de base, ce qui constitue une clé primaire bonne est largement laissé à la religion et aux arguments de la salle de pause. Si vous avez quelque chose qui est et sera toujours mappé de manière unique à une ligne individuelle, cela fonctionnera bien comme clé primaire. Passé ce point, il y a d'autres considérations:
Ce dernier est probablement ce qui attire la plupart des gens à utiliser des choses comme les GUID ou les colonnes entières auto-incrémentées, car en s'appuyant sur des choses comme les adresses, les numéros de téléphone, les prénoms/noms de famille, etc., ne le coupez pas. Le seul invariant à propos des gens auquel je peux penser est les SSN, mais je ne suis même pas sûr à 100% de ceux qui restent éternellement uniques.
Espérons que cela aide à ajouter de la clarté ...
La façon dont j'aborde les clés primaires (et je pense que c'est le meilleur) est d'éviter d'avoir une approche "par défaut". Cela signifie qu'au lieu de simplement gifler sur un entier à incrémentation automatique et de l'appeler un jour, je regarde le problème et je dis "y a-t-il une colonne ou un groupe de colonnes qui seront toujours inexactes et ne changeront pas?" Si la réponse est oui, je prends cette approche.
Presque toujours des entiers.
Ils ont d'autres bonnes raisons en plus d'être plus petits/plus rapides à traiter. Lequel préférez-vous écrire - "404040" ou "3463b5a2-a02b-4fd4-aa0f-1d3c0450026c"?
C'est un sujet complexe, que vous l'ayez réalisé ou non. Pourrait tomber sous la section de cette FAQ StackOverflow.
Quel genre de questions ne devrais-je pas poser ici?
Évitez de poser des questions subjectives, argumentatives ou nécessitant une discussion approfondie. C'est un endroit pour les questions auxquelles on peut répondre!
Cela a été débattu pendant des années et continuera d'être débattu pendant des années. Le seul indice de consensus que j'ai vu est que les réponses sont quelque peu prévisibles selon que vous demandez à un OO gars (les GUID sont la seule façon de procéder!), Un modélisateur de données (clés naturelles sont le seul chemin à parcourir!), ou un DBA axé sur les performances (les INT sont le seul chemin à parcourir!).