Dans une discussion assez animée dans mon équipe, on m'a fait penser à ce que la plupart des gens aiment comme clés primaires. Nous avions les groupes suivants-
- Int / BigInt dont l'auto-incrémentation sont des clés primaires assez bonnes.
- Il doit y avoir au moins 3 colonnes qui constituent la clé primaire.
- L'ID, le GUID et les identificateurs de ligne lisibles par l'homme doivent tous être traités différemment.
Quelle est la meilleure approche pour les PK? Ce serait génial si vous pouviez justifier votre opinion. Y a-t-il une meilleure approche que celle ci-dessus?
EDIT: N'importe qui a un simple exemple / algorithme pour générer des identifiants lisibles par l'homme pour les lignes qui s'adaptent bien?
algorithm
database-design
relational-database
primary-key
ddl
Perpetualcoder
la source
la source
PK(NEWID(),NEWID(),NEWID())
;-)Réponses:
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 un peu pénible pour le débogage, donc à part ce cas, j'ai tendance à m'en tenir à cet auto-incrémentation.
Les entiers d'auto-incrémentation doivent être votre valeur par défaut, et ne pas les utiliser doit être justifié.
la source
CHAR(1)
aurait suffi, comme poursex
. Inutile de dire que c'était un cauchemar avec lequel travailler.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 de mauvais choix pour la clé primaire.
Par exemple, dans un tableau de noms et de codes d'état (américains), 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é 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 du monde réel.
Lorsqu'il s'agit de déterminer la clé primaire d'une table donnée, vous devez donc regarder ce que représente cette table. Quel ensemble ou ensembles de valeurs de colonne dans la table identifie de manière unique chaque ligne de la table? Ce sont les clés candidates. Maintenant, si chaque clé candidate se compose de 4 ou 5 colonnes, vous pouvez décider que celles-ci sont trop maladroites pour constituer 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 de 32 bits est suffisant pour la clé de substitution. 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 en tant qu'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 simplement répéter une information ne la rend pas 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 existe un danger (surtout si vous utilisez des curseurs) que vous ne mettiez à jour qu'une seule ligne. plutôt que chaque ligne, de sorte que 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 avec l'utilisation d'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 bonne suffit. L'utilisation d'un GUID où une valeur de 4 octets suffirait gaspille 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 devront être lues pour accéder au information.
la source
Ce n'est qu'un problème religieux parce que les gens recherchent une bonne réponse universelle. Le fait que votre équipe et ce fil SO montrent autant de désaccords devrait être un indice qu'il existe de bonnes raisons d'utiliser toutes les solutions que vous décrivez, dans des circonstances différentes.
state
(CA, TX, NY), vous pouvez également utiliser unchar(2)
clé naturelle au lieu d'un int.id
inutilement une clé de substitution " lorsqu'une clé composée parfaitement bonne existe (ceci est particulièrement vrai dans les tables plusieurs-à-plusieurs). Un mandat pour une clé à trois colonnes dans chaque table est un non-sens absolu.la source
J'aime le blog The Database Programmer en tant que source de 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é.
la source
J'aime le mien unique.
la source
Un peu hors sujet, mais je me sens obligé d'intervenir avec ...
Si votre clé primaire est un GUID, n'en faites pas un index cluster . É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.
la source
J'y vais toujours avec la clé de substitution. Une clé de substitution (généralement une colonne d'identité, un 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 véritables clés naturelles. Même des choses comme le SSN aux États-Unis ne sont pas une clé naturelle. Les clés primaires composites sont un désastre qui attend. Vous ne pouvez modifier aucune de ces données (ce qui est le principal inconvénient de toute clé naturelle, composite ou non), mais le pire est qu'avec une clé composite, vous devez maintenant perpétuer ces données clés 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 volumineux et Microsoft recommande de ne pas les utiliser comme PK. Si vous avez plusieurs serveurs, tout ce que vous avez à faire est de faire l'incrément de 10 ou 20 ou tout ce que vous pensez du nombre maximum de serveurs dont vous aurez jamais besoin pour synchroniser / étendre, et simplement ajouter la graine pour chaque table sur chaque serveur suivant , et vous n'aurez jamais de collision de données.
Bien sûr, à cause de l'incrément, je fais de la colonne d'identité un BigInt (autrement connu sous le nom de long [64 bits]).
En faisant un peu de calcul, même si vous faites l'incrément de 100, vous pouvez toujours avoir 92 233 720 368 547 758 (> 92 quadrillions) lignes dans votre tableau.
la source
Je pense que l'utilisation du mot «primaire», dans l'expression «clé primaire» est dans un vrai sens trompeur.
Tout d'abord, utilisez la définition selon laquelle une "clé" est un attribut ou un ensemble d'attributs qui doivent être uniques dans la table,
Ensuite, avoir une clé sert plusieurs objectifs souvent incompatibles entre eux.
Pour augmenter la performance des requêtes qui doivent localiser rapidement un enregistrement / une ligne spécifique dans le tableau.
Pour assurer la cohérence des données en empêchant les lignes dupliquées qui représentent la même entité logique d'être insérées dans la table. (Ceci est souvent appelé une clé «naturelle», et devrait être constitué d'attributs de table (entité) qui sont relativement invariants.)
Clairement, 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 beaucoup (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 à des fins # 1, # 2 ou # 3 sera inacceptable performances conséquencecs.
La réponse est simple. Utilise les deux. Utilisez une simple clé intégrale à génération automatique pour toutes les jointures et FK des autres tables enfants, mais assurez-vous que chaque table nécessitant la cohérence des données (très peu de tables ne le fait pas) dispose d'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 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 dupliquées incohérentes ...
En ce qui concerne les GUID, soyez très prudent en les utilisant, car l'utilisation de guides dans un index peut réduire 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 binaires 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.
la source
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 endroit, où la clé primaire était l'ID de compte, qui était une combinaison de lettres et de chiffres. Je ne me souviens pas de détails, mais, par exemple, les comptes qui étaient d'un certain type, seraient dans la gamme 600, et d'un autre type, commençaient par 400. C'était génial, jusqu'à ce que ce client décide de demander les deux types de travail. Ou changé le type de travail qu'ils faisaient.
Un autre endroit, utilisé l'emplacement dans l'arborescence comme clé primaire pour les enregistrements. Il y aurait donc des enregistrements comme celui-ci.
Bien sûr, la première chose que les clients voulaient était un moyen de déplacer les articles dans l'arborescence. 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, veuillez ne pas utiliser de clé intelligente!
la source
Je suis fan de l'incrémentation automatique comme clé primaire. Je sais au fond de moi qu'il s'agit d'une échappatoire, mais cela rend si facile de trier les données par quand elles ont été ajoutées (ORDER BY ID DESC, f'r instance).
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 par un humain qui l'interroge (par rapport à la procédure stockée ou à l'interface de programmation).
l'auto-incrémentation est pour nous les humains. :-(
la source
En général, cela dépend.
Personnellement, j'aime les ints auto-incrémentés.
Mais, une chose que je peux vous dire est de ne jamais faire confiance aux données provenant d'autres sources comme votre clé. Je le jure, chaque fois que je fais ça, ça me mord. Eh bien, plus jamais!
la source
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 portant le même nom) ou ne sont pas constantes (quelqu'un peut changer de nom).
Je préfère Guid. Un problème potentiel avec l'auto-incrémentation est que la valeur (par exemple, "order id") est attribuée par l'instance de base de données (par exemple par la "base de données des ventes") ... ce qui ne fonctionnera pas entièrement (au lieu de cela, vous commencez à avoir besoin de clés composées) si vous devez jamais fusionner des données créées par plus d'une instance de base de données (par exemple à partir de plusieurs bureaux de vente, chacun avec sa propre base de données).
la source
GUID RE
Faites attention si cela va être une très VRAIMENT VRAIMENT VRAIMENT grosse 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 spécialistes des bases de données se sont fermement 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 la mémoire interne pour une chaîne Guid - par rapport à une valeur décimale ferait une différence très notable dans les recherches. (Clés 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 de disque.
la source
Colonnes à incrémentation automatique. Je suis capable de faire fonctionner mon code de manière 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.
la source
J'ai toujours utilisé une clé de substitution - un entier à auto-incrémentation 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:
les raisons raisonnables contre lesquelles je n'ai pas encore pensé ou rencontrées sont toujours les bienvenues ...
la source
C'est un classique "ça dépend". Il n'y a pas une seule 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 onglets et les espaces.
la source
J'ai tendance à utiliser l'option n ° 1 ou n ° 3 selon la taille, le nombre de personnes qui se connectent et s'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 apparaissent 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.
la source
Je n'utilise qu'un int auto-incrémenté ou un GUID. 99% du temps, j'utilise des int auto-incrémentés. C'est exactement ce que j'ai appris à utiliser lorsque j'ai découvert les bases de données pour la première fois et que je n'ai jamais rencontré de raison de ne pas les utiliser (même si je connais les raisons pour lesquelles un GUID serait meilleur).
J'aime les incréments automatiques 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.
la source
Au-delà d'une réponse définitionnelle de base, ce qui constitue une bonne clé primaire est largement laissé aux arguments de la religion et de la salle de repos. Si vous avez quelque chose qui est et sera toujours mappé de manière unique à une ligne individuelle, cela fonctionnera bien en tant que clé primaire. Passé ce stade, il y a d'autres considérations:
Ce dernier est probablement ce qui incite la plupart des gens à utiliser des éléments tels que les GUID ou des colonnes d'entiers auto-incrémentées, car en s'appuyant sur des éléments tels que les adresses, les numéros de téléphone, les prénoms / noms, etc., ne le coupez pas. Le seul invariant des personnes auquel je peux penser est les SSN, mais je ne suis même pas sûr à 100% que ceux-ci resteront à jamais uniques.
Espérons que cela contribue à ajouter de la clarté ...
la source
La façon dont j'aborde les clés primaires (et je pense que c'est la meilleure) est d'éviter d'avoir une approche «par défaut». Cela signifie qu'au lieu de simplement taper sur un entier auto-incrémenté et de l'appeler un jour, je regarde le problème et dis "y a-t-il une colonne ou un groupe de colonnes qui sera toujours unique et ne changera pas?" Si la réponse est oui, j'adopte cette approche.
la source
Presque toujours des nombres 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"?
la source
Ce n'est que légèrement pertinent, mais une chose que j'ai commencé à faire récemment lorsque j'ai de petites tables de classification (essentiellement celles qui représenteraient les ENUM dans le code) est que je vais faire de la clé primaire un char (3) ou char (4). Ensuite, je rends 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 ligne de devis est affecté à l'un des ... 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 stockent plus de détails, tels que la signification anglaise normale 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 à ceci:
1 Numéro de pièce 40 $ MTL
2 Autre numéro de pièce 29,99 $ SVC
3 Numéro de pièce2 150 $ TRV
Il est beaucoup plus facile d'utiliser un int pour représenter les catégories, puis de relier 1, 2, 3 sur toutes les lignes - vous avez les données juste là devant vous, et la performance ne semble pas du tout affectée (pas que je '' vraiment testé.)
En ce qui concerne la vraie question ... j'aime les identificateurs uniques RowGUID. Je ne suis pas à 100% là-dessus, mais toutes les lignes n'ont-elles pas de RowGuid interne de toute façon ?? Si tel est le cas, utiliser RowGuid prendrait en fait moins de place que ints (ou quoi que ce soit d'autre d'ailleurs). Tout ce que je sais, c'est que si c'est assez bon pour M $ à utiliser dans GreatPlains, alors c'est assez bien pour moi. (Dois-je esquiver ??)
la source
Oh, une autre raison pour laquelle j'utilise des GUID - j'utilise une structure de données hiérarchique. Autrement dit, j'ai une table «Entreprise» et une table «Fournisseur» pour lesquelles les clés primaires correspondent. Mais j'ai aussi une table «Fabricant» qui «hérite» également de Company. Les champs communs aux fournisseurs et aux fabricants n'apparaissent pas dans ces tableaux - ils apparaissent dans Société. Dans cette configuration, utiliser des int est beaucoup plus douloureux que les Guids. À tout le moins, vous ne pouvez pas utiliser de clés primaires d'identité.
la source
J'aime les clés naturelles, chaque fois que je peux leur faire confiance. Je suis prêt à payer un petit prix de performance afin d'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 doit y avoir une clé naturelle simple qui identifie les instances individuelles de la même manière que les sujets. Si le sujet n'a pas d'identifiants fiables pour l'une des entités, je recourrai à une clé de substitution.
Pour les tables qui décrivent les 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é. Encore une fois, la performance de l'utilisation d'une clé composée est généralement minime.
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 seule table. Logiquement, chacun est aussi bon qu'un autre. Choisir l'un d'entre eux comme "primaire" et faire toutes les références via cette clé est simplement un choix que le concepteur peut faire.
la source
Guids.period.
Dans le cas où vous auriez besoin d'évoluer ou d'attribuer la clé primaire par d'autres moyens, ils seront votre ami. Vous pouvez ajouter des index pour tout le reste.
mise à jour pour clarifier ma déclaration.
J'ai travaillé sur de nombreux types de sites. Des petites offres de serveur unique aux grandes offres avec plusieurs serveurs de base de données et Web. Il y a certainement eu des applications qui auraient été très bien avec l'incrémentation automatique des ints en tant que clés primaires. Cependant, cela ne correspond 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 auto-incrémenté ne peut être généré en toute sécurité que dans la base de données primaire. Encore une fois, cela pourrait convenir si vous avez une application qui sera intimement liée à ce serveur de base de données de sauvegarde et que la mise à l'échelle n'est pas quelque chose qui vous préoccupe.
Bien sûr, l'utilisation de GUID signifie que vous devez avoir des processus de réindexation nocturnes. Cependant, si vous utilisez autre chose qu'un INT auto-incrémenté, 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 gérer la fragmentation. Par conséquent, l'utilisation de GUID n'ajoute pas exactement un autre problème car ces tâches doivent être exécutées malgré tout.
Si vous jetez un œil aux applications plus volumineuses, 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 de GUID vous permet de passer facilement à l'échelle , alors qu'il peut y avoir beaucoup d'obstacles à franchir lors de la tentative de mise à l'échelle des INT.
Notre dernière application traverse une période d'insertions lourdes qui dure environ un mois. Après cela, plus de 90% des requêtes sont toutes sélectionnées pour la création de rapports. Pour augmenter la capacité, je peux installer des serveurs de base de données supplémentaires pendant cette grande période d'insertion; puis les fusionner facilement en une seule base de données pour la création de rapports. Tenter de faire cela avec des INT serait un cauchemar absolu.
Franchement, chaque fois que vous mettez en cluster une base de données ou que vous configurez une réplication, le serveur de base de données vous demandera de toute façon d'avoir des GUID sur la table. Donc, si vous pensez que votre système pourrait avoir besoin de se développer, choisissez celui qui est bon.
la source
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 dois-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 fait l'objet de débats depuis des années et continuera de l'être 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 gars OO (les GUID sont la seule voie à suivre!), Un modeleur de données (les clés naturelles sont la seule voie à suivre!), ou un DBA orienté performance (les INT sont la seule solution!).
la source