web-dev-qa-db-fra.com

Quelle est la meilleure pratique pour les clés primaires dans les tables?

Lors de la conception des tables, j'ai pris l'habitude d'avoir une colonne unique et de créer la clé primaire. Ceci est réalisé de trois manières en fonction des besoins:

  1. Colonne entière d'identité qui s'incrémente automatiquement.
  2. Identifiant unique (GUID)
  3. Colonne de type caractère court (x) ou entier (ou autre type numérique relativement petit) pouvant servir de colonne d'identificateur de ligne

Le numéro 3 serait utilisé pour une recherche relativement petite, principalement des tables de lecture pouvant comporter un code de chaîne de longueur statique unique ou une valeur numérique telle qu'une année ou un autre nombre.

Pour la plupart, toutes les autres tables auront soit un entier auto-incrémenté, soit un identifiant unique.

La question :-)

J'ai récemment commencé à travailler avec des bases de données qui n'ont pas d'identificateur de ligne cohérent et les clés primaires sont actuellement regroupées en plusieurs colonnes. Quelques exemples:

  • date/caractère
  • date/heure
  • date/varchar
  • char/nvarchar/nvarchar

Y at-il un cas valable pour cela? J'aurais toujours défini une colonne d'identité ou d'identificateur unique pour ces cas.

De plus, il existe de nombreuses tables sans clé primaire. Quelles sont les raisons valables, le cas échéant, pour cela?

J'essaie de comprendre pourquoi les tables ont été conçues comme elles étaient, et cela semble être un gros désastre pour moi, mais il y avait peut-être de bonnes raisons pour cela.

Une troisième question pour m'aider à déchiffrer les réponses: dans les cas où plusieurs colonnes sont utilisées pour comprendre la clé primaire composée, cette méthode présente-t-elle un avantage spécifique par rapport à une clé de substitution/clé artificielle? Je pense surtout à la performance, la maintenance, l’administration, etc.?

240
Lloyd Cotten

Je suis quelques règles:

  1. Les clés primaires doivent être aussi petites que nécessaire. Préférez un type numérique car les types numériques sont stockés dans un format beaucoup plus compact que les formats de caractères. Cela est dû au fait que la plupart des clés primaires seront des clés étrangères dans une autre table et utilisées dans plusieurs index. Plus votre clé est petite, plus l'index est petit, moins vous utiliserez de pages dans le cache.
  2. Les clés primaires ne devraient jamais changer. La mise à jour d'une clé primaire devrait toujours être hors de question. En effet, il est fort probable qu'il soit utilisé dans plusieurs index et utilisé comme clé étrangère. La mise à jour d'une clé primaire unique peut avoir un effet d'entraînement sur les modifications.
  3. N'utilisez PAS "votre clé primaire de problème" comme clé primaire de votre modèle logique. Par exemple, le numéro de passeport, le numéro de sécurité sociale ou le numéro de contrat de l'employé, ces "clés primaires" pouvant changer pour des situations réelles.

Sur clé de substitution vs clé naturelle, je me réfère aux règles ci-dessus. Si la clé naturelle est petite et ne changera jamais, elle peut être utilisée comme clé primaire. Si la clé naturelle est grande ou susceptible de changer, j'utilise des clés de substitution. S'il n'y a pas de clé primaire, je crée toujours une clé de substitution, car l'expérience montre que vous ajouterez toujours des tables à votre schéma et que vous souhaitiez mettre une clé primaire en place.

232
Logicalmind

Les vers naturels des clés artificielles sont une sorte de débat religieux au sein de la communauté de la base de données - voir cet article et autres auxquels il renvoie. Je ne suis pas en faveur de toujours avoir des clés artificielles, ni de jamais les avoir. Je déciderais au cas par cas, par exemple:

  • États américains: je choisirais state_code ('TX' pour le Texas, etc.), plutôt que state_id = 1 pour le Texas
  • Employés: je crée généralement un id_employé artificiel, car il est difficile de trouver autre chose qui fonctionne. Le SSN ou l’équivalent peut fonctionner, mais des problèmes peuvent survenir, par exemple, pour un nouveau membre qui n’a pas encore fourni son SSN.
  • Historique des salaires des employés: (employee_id, start_date). Je voudrais ne pas créer un employé artificiel_salary_history_id. Quel point cela servirait-il (autre que "consistance stupide" )

Partout où des clés artificielles sont utilisées, vous devez également toujours déclarer des contraintes uniques sur les clés naturelles. Par exemple, utilisez state_id si vous devez, mais vous feriez mieux de déclarer une contrainte unique sur state_code, sinon vous êtes sûr de vous retrouver avec:

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas
87
Tony Andrews

Juste un commentaire supplémentaire sur quelque chose qui est souvent négligé. Parfois, le fait de ne pas utiliser de clé de substitution présente des avantages dans les tables enfants. Supposons que notre conception vous permette de gérer plusieurs sociétés dans la même base de données (peut-être une solution hébergée, ou autre).

Disons que nous avons ces tables et colonnes:

Company:
  CompanyId   (primary key)

CostCenter:
  CompanyId   (primary key, foreign key to Company)
  CostCentre  (primary key)

CostElement
  CompanyId   (primary key, foreign key to Company)
  CostElement (primary key)

Invoice:
  InvoiceId    (primary key)
  CompanyId    (primary key, in foreign key to CostCentre, in foreign key to CostElement)
  CostCentre   (in foreign key to CostCentre)
  CostElement  (in foreign key to CostElement)

Si ce dernier bit n'a pas de sens, Invoice.CompanyId fait partie de deux clés étrangères, l'une vers la table CostCentre et l'autre vers la table CostElement. La clé primaire est (InvoiceId, CompanyId).

Dans ce modèle, il n'est pas possible de visionner et de référencer un CostElement d'une société et un CostCentre d'une autre société. Si une clé de substitution était utilisée sur les tables CostElement et Tables CostCentre, ce serait le cas.

Moins il y a de chances de foirer, mieux c'est.

25
WW.

J'évite d'utiliser des clés naturelles pour une raison simple: l'erreur humaine. Bien que des identifiants uniques et naturels soient souvent disponibles (SSN, VIN, numéro de compte, etc.), ils ont besoin d'un humain pour les saisir correctement. Si vous utilisez des SSN en tant que clé primaire, si quelqu'un transpose quelques chiffres lors de la saisie de données et si l'erreur n'est pas découverte, vous devez alors modifier votre clé primaire.

Mes clés primaires sont toutes gérées par le programme de base de données en arrière-plan et l'utilisateur n'en est jamais conscient.

21
Paul

Il n’ya aucun problème à créer votre clé primaire à partir de divers champs, c’est une clé naturelle .

Vous pouvez utiliser une colonne Identity (associée à un index unique sur les champs candidats) pour créer une clé de substitution .

C'est une vieille discussion. Je préfère les clés de substitution dans la plupart des situations.

Mais il n’ya aucune excuse pour l’absence de clé.

RE: EDIT

Oui, il y a beaucoup de controverse à ce sujet: D

Je ne vois aucun avantage évident sur les clés naturelles, mis à part le fait qu’elles constituent le choix naturel. Vous penserez toujours en nom, numéro social - ou quelque chose comme ça - au lieu de idPerson .

Les clés de substitution sont la réponse à certains des problèmes des clés naturelles (propagation des modifications, par exemple).

À mesure que vous vous habituez aux mères porteuses, cela semble plus propre et plus facile à gérer.

Mais à la fin, vous découvrirez qu’il s’agit simplement d’une question de goût - ou de mentalité -. Les gens "pensent mieux" avec des clés naturelles, d’autres pas.

13

Les tables doivent toujours avoir une clé primaire. Dans le cas contraire, il aurait dû s'agir d'un champ AutoIncrement.

Parfois, les personnes omettent la clé primaire car elles transfèrent beaucoup de données et cela peut ralentir (en fonction de la base de données) le processus. MAIS, il devrait être ajouté après.

Quelque chose à propos de la table des liens, c'est vrai, c'est une exception MAIS les champs doivent être FK pour conserver l'intégrité. Dans certains cas, ces champs peuvent également être des clés primaires si la duplication dans les liens n'est pas autorisée. .. mais pour rester dans un formulaire simple, car l’exception est quelque chose de souvent programmé, une clé primaire doit être présente pour préserver l’intégrité de vos données.

11
Patrick Desjardins

Outre toutes ces bonnes réponses, je souhaite simplement partager un bon article que je viens de lire, Le grand débat sur la clé primaire.

Juste pour citer quelques points:

Le développeur doit appliquer quelques règles lors du choix d'une clé primaire pour chaque table:

  • La clé primaire doit identifier chaque enregistrement de manière unique.
  • La valeur de la clé primaire d’un enregistrement ne peut pas être nulle.
  • La clé-valeur primaire doit exister lors de la création de l'enregistrement.
  • La clé primaire doit rester stable. Vous ne pouvez pas modifier le ou les champs de clé primaire.
  • La clé primaire doit être compacte et contenir le moins d'attributs possibles.
  • La valeur de la clé primaire ne peut pas être modifiée.

Les clés naturelles (tendent à) enfreignent les règles. Les clés de substitution sont conformes aux règles. (Vous feriez mieux de lire cet article, ça vaut votre temps!)

8
RayLuo

Quelle est la particularité de la clé primaire?

Quel est le but d'une table dans un schéma? Quel est le but d'une clé d'une table? Quelle est la particularité de la clé primaire? Les discussions autour des clés primaires semblent oublier que la clé primaire fait partie d'une table et que cette table fait partie d'un schéma. Ce qui convient le mieux à la table et les relations entre les tables doivent déterminer la clé utilisée.

Les tables (et leurs relations) contiennent des informations sur les informations que vous souhaitez enregistrer. Ces faits doivent être autonomes, significatifs, faciles à comprendre et non contradictoires. Du point de vue de la conception, les autres tables ajoutées ou supprimées d’un schéma ne devraient pas avoir d’impact sur la table en question. Il doit y avoir un but pour stocker les données liées uniquement aux informations elles-mêmes. Comprendre ce qui est stocké dans une table ne devrait pas nécessiter un projet de recherche scientifique. Aucun fait stocké dans le même but ne doit être stocké plus d'une fois. Les clés sont un ensemble ou une partie des informations enregistrées qui sont uniques, et la clé primaire est la clé spécialement désignée qui doit être le principal point d'accès à la table (c.-à-d. Qu'elle devrait être choisie pour la cohérence et l'utilisation des données, et non simplement pour l'insertion. performance).

  • EN OUTRE: Malheureusement, la plupart des bases de données conçues et développées par des programmeurs d’applications (ce que je suis parfois) ont malheureusement comme effet secondaire que ce qui est le mieux pour l’application ou le framework d’application détermine souvent le choix de la clé principale pour les tables. Cela conduit aux clés entier et GUID (simples à utiliser pour les frameworks d'application) et aux conceptions monolithiques (car elles réduisent le nombre d'objets de framework d'application nécessaires pour représenter les données en mémoire). Ces décisions de conception de bases de données pilotées par les applications posent d'importants problèmes de cohérence des données lorsqu'elles sont utilisées à grande échelle. Les cadres d'application conçus de cette manière mènent naturellement à des conceptions de table à la fois. Les "enregistrements partiels" sont créés dans des tables et les données sont renseignées au fil du temps. Les interactions entre plusieurs tables sont évitées ou, lorsqu'elles sont utilisées, provoque des données incohérentes lorsque l'application fonctionne mal. Ces conceptions génèrent des données dénuées de sens (ou difficiles à comprendre), des données réparties sur des tableaux (vous devez consulter d'autres tableaux pour donner un sens au tableau actuel) et des données dupliquées.

On a dit que les clés primaires devraient être aussi petites que nécessaire. Je dirais que les clés devraient être aussi grandes que nécessaire. L'ajout aléatoire de champs sans signification à une table doit être évité. Il est encore pire de créer une clé à partir d'un champ sans signification ajouté de manière aléatoire, en particulier lorsqu'il détruit la dépendance de la jointure d'une autre table à la clé non primaire. Cela n’est raisonnable que s’il n’ya pas de bonne clé candidate dans la table, mais cette occurrence est sûrement le signe d’une mauvaise conception de schéma si elle est utilisée pour toutes les tables.

Il a également été dit que les clés primaires ne devraient jamais changer car la mise à jour d'une clé primaire devrait toujours être hors de question. Mais la mise à jour est la même chose que supprimer suivi d'insérer. Selon cette logique, vous ne devez jamais supprimer un enregistrement d'une table avec une clé, puis ajouter un autre enregistrement avec une seconde clé. L'ajout de la clé primaire de substitution ne supprime pas le fait que l'autre clé de la table existe. La mise à jour d'une clé non primaire d'une table peut détruire la signification des données si d'autres tables dépendent de cette signification par le biais d'une clé de substitution (par exemple, une table de statut avec une clé de substitution dont la description de statut a été modifiée de 'Traitée' à 'Annulée 'corromprait définitivement les données). Ce qui devrait toujours être hors de question est de détruire le sens des données.

Cela dit, je suis reconnaissant des nombreuses bases de données mal conçues qui existent dans les entreprises actuelles (monstres 1NF sans clé), car cela signifie que les personnes qui comprennent la conception de bases de données doivent travailler sans relâche. . Mais du côté triste, cela me fait parfois penser à Sisyphe, mais je parie qu’il avait un sacré 401k (avant le crash). Éloignez-vous des blogs et des sites Web pour des questions importantes sur la conception de bases de données. Si vous concevez des bases de données, recherchez CJ Date. Vous pouvez également faire référence à Celko pour SQL Server, mais uniquement si vous vous tenez le premier. Du côté Oracle, faites référence à Tom Kyte.

7
Luke

Une clé naturelle, si disponible, est généralement la meilleure. Donc, si datetime/char niquement identifie la ligne et que les deux parties ont un sens pour la ligne, c'est très bien.

Si seul le paramètre datetime est significatif et que le caractère est simplement ajouté pour le rendre unique, vous pouvez également utiliser un champ d'identification.

6
James Curran

Pour moi, les clés naturelles par opposition aux clés artificielles dépendent de la quantité de logique métier que vous souhaitez dans votre base de données. numéro de sécurité sociale (SSN) est un excellent exemple.

"Chaque client de ma base de données aura et devra avoir un SSN." Bam, c’est fait, faites-en la clé primaire et finissez-en. N'oubliez pas que lorsque vos règles métier changent, vous êtes brûlé.

Je n'aime pas les clés naturelles moi-même, en raison de mon expérience de la modification des règles de gestion. Mais si vous êtes certain que cela ne changera pas, cela pourrait éviter quelques jointures critiques.

5
Dan Williams

Je soupçonne que Steven A. Lowe doit avoir recours à la thérapie par journal pour le concepteur de la structure de données originale.

Mis à part, GUID en tant que clé primaire peut être une mauvaise performance. Je ne le recommanderais pas.

4
Andrew Rollings

Je cherche des clés primaires naturelles et les utilise où je peux.

Si aucune clé naturelle ne peut être trouvée, je préfère un GUID à un INT ++ car SQL Server utilise des arborescences et qu'il est mauvais de toujours ajouter des clés à la fin des arborescences.

Sur les tables qui sont plusieurs couplages, j'utilise une clé primaire composée des clés étrangères.

Parce que j'ai la chance d'utiliser SQL Server, je peux étudier les plans d'exécution et les statistiques avec le profileur et l'analyseur de requêtes et découvrir comment mes clés fonctionnent très facilement.

3
Guge

Vous devez utiliser une clé primaire "composite" ou "composée" composée de plusieurs champs.

C'est une solution parfaitement acceptable, allez ici pour plus d'informations :)

3
adam

Moi aussi, j'utilise toujours une colonne d'identifiant numérique. Dans Oracle, j'utilise numéro (18,0) sans raison réelle au-dessus du nombre (12,0) (ou ce qui est un entier plutôt que long), peut-être que je ne veux tout simplement pas m'inquiéter d'avoir quelques milliards de lignes dans le db!

J'inclus également une colonne créée et modifiée (type timestamp) pour le suivi de base, où cela semble utile.

Cela ne me dérange pas de définir des contraintes uniques sur d'autres combinaisons de colonnes, mais j'aime beaucoup mon identifiant, mes exigences de base créées et modifiées.

3
JeeBee

Voici ma règle de base sur laquelle je me suis établi après plus de 25 ans d'expérience en développement.

  • Toutes les tables doivent avoir une clé primaire de colonne unique qui s'incrémente automatiquement.
  • Incluez-le dans toute vue destinée à être mise à jour
  • La clé primaire ne doit avoir aucune signification dans le contexte de votre application. Cela signifie qu'il ne devrait pas s'agir d'une SKU, d'un numéro de compte, d'un identifiant d'employé ou de toute autre information significative pour votre application. C'est simplement une clé unique associée à une entité.

La clé primaire est utilisée par la base de données à des fins d'optimisation et votre application ne doit pas l'utiliser uniquement pour identifier une entité particulière ou en relation avec une entité particulière.

Le fait de toujours avoir une clé primaire à valeur unique facilite l'exécution des actions UPSERT.

Utilisez des index supplémentaires pour prendre en charge les clés multi-colonnes ayant une signification dans votre application.

3

J'utilise toujours un numéro automatique ou un champ d'identité.

J'ai travaillé pour un client qui utilisait le SSN comme clé primaire et qui, à cause de la réglementation HIPAA, était obligé de passer à un "MemberID", ce qui causait une tonne de problèmes lors de la mise à jour des clés étrangères dans les tables associées. Le fait de respecter une norme cohérente en matière de colonne d’identité m’a permis d’éviter un problème similaire dans tous mes projets.

2
Matt

GUID peut être utilisé comme clé primaire, mais vous devez créer le bon type de GUID pour qu'il fonctionne correctement.

Vous devez générer des GUID COMB. Un bon article à ce sujet et sur les statistiques de performance est Le coût des GUID en tant que clés primaires.

De plus, du code sur la construction de GUID COMB dans SQL est dans niqueidentifier vs identity ( archive ) .

1
Donny V.

Toutes les tables devraient ont une clé primaire. Sinon, ce que vous avez est un HEAP - ceci, dans certaines situations, peut être ce que vous voulez (charge d'insertion importante lorsque les données sont ensuite répliquées via un courtier de service vers une autre base de données ou une autre table, par exemple).

Pour les tables de consultation avec un faible volume de lignes, vous pouvez utiliser un code 3 CHAR comme clé primaire car cela prend moins de place qu'un INT, mais la différence de performances est négligeable. En dehors de cela, j'utiliserais toujours un INT, sauf si vous avez une table de référence contenant peut-être une clé primaire composite composée de clés étrangères issues de tables associées.

1
Coolcoder

Si vous voulez vraiment lire tous les échanges sur ce débat séculaire, lancez une recherche sur "clé naturelle" sur Stack Overflow. Vous devriez récupérer les pages de résultats.

1
Tom H

Je parlerai tout de suite de ma préférence pour les clés naturelles - utilisez-les autant que possible, car elles faciliteront grandement votre vie d'administration de bases de données. J'ai établi dans notre entreprise un standard selon lequel toutes les tables ont les colonnes suivantes:

  • ID de ligne (GUID)
  • Créateur (chaîne; valeur par défaut du nom de l'utilisateur actuel (SUSER_SNAME() dans T-SQL))
  • Créé (DateTime)
  • Horodatage

L'ID de ligne a une clé unique par table et, dans tous les cas, elle est générée automatiquement par ligne (et les autorisations empêchent toute modification), et il est raisonnablement garanti qu'elle est unique dans toutes les tables et bases de données. Si un système ORM nécessite une seule clé d'identification, c'est celle-ci à utiliser.

Pendant ce temps, la PC réelle est, si possible, une clé naturelle. Mes règles internes sont quelque chose comme:

  • Personnes - utilisez la clé de substitution, par exemple INT. Si c'est interne, l'utilisateur Active Directory GUID est un choix acceptable
  • Tables de consultation (par exemple, StatusCodes) - utilisez un code CHAR court; il est plus facile à mémoriser que les INT, et dans de nombreux cas, les formulaires papier et les utilisateurs l'utilisent également par souci de brièveté (par exemple, Status = "E" pour "Expiré", "A" pour "Approuvé", "NADIS" pour "Aucun amiante détecté" Dans l'échantillon ")
  • Tables de liaison - combinaison de FK (par exemple EventId, AttendeeId)

Donc, idéalement, vous vous retrouvez avec une PK naturelle, lisible par l'homme et mémorable, ainsi qu'un GUID à un ID par table et respectant l'ORM.

Mise en garde: les bases de données que je maintiens ont tendance à contenir des centaines de milliers d'archives plutôt que des millions ou des milliards. Si vous avez l'expérience de systèmes plus volumineux qui contre-indiquent mes conseils, n'hésitez pas à m'ignorer!

0
Keith Williams

Nous faisons beaucoup de jointures et les clés primaires composites viennent tout juste de devenir une performance. Un simple int ou long prend en charge de nombreux problèmes même si vous introduisez une deuxième clé candidate, mais il est beaucoup plus facile et plus compréhensible de joindre un domaine à trois.

0
Dan Blair