web-dev-qa-db-fra.com

Est-ce une bonne pratique de toujours avoir une clé primaire entière à incrémentation automatique?

Dans mes bases de données, j'ai tendance à prendre l'habitude d'avoir une clé primaire entière à incrémentation automatique avec le nom id pour chaque table que je crée afin d'avoir une recherche unique pour une ligne particulière.

Est-ce considéré comme une mauvaise idée? Y a-t-il des inconvénients à le faire de cette façon? Parfois, j'ai plusieurs indices comme id, profile_id, subscriptionsid est l'identifiant unique, profile_id des liens vers le id étranger d'une table Profile, etc.

Ou existe-t-il des scénarios dans lesquels vous ne souhaitez pas ajouter un tel champ?

198
AJJ

Ce n'est jamais une mauvaise idée d'avoir un identifiant de ligne unique garanti. Je suppose que je ne devrais pas dire jamais - mais allons-y avec l'écrasante majorité du temps, c'est une bonne idée.

Les inconvénients potentiels théoriques incluent un index supplémentaire à maintenir et un espace de stockage supplémentaire utilisé. Cela n'a jamais été une raison suffisante pour que je n'en utilise pas.

138
GrandmasterB

Je suis en désaccord avec toutes les réponses précédentes. Il y a de nombreuses raisons pour lesquelles c'est une mauvaise idée d'ajouter un champ d'incrémentation automatique dans toutes les tables.

Si vous avez une table où il n'y a pas de clés évidentes, un champ d'incrémentation automatique semble être une bonne idée. Après tout, vous ne voulez pas select * from blog where body = '[10000 character string]'. Vous préférez select * from blog where id = 42. Je dirais que dans la plupart de ces cas, ce que vous voulez vraiment, c'est un identifiant unique; pas un identifiant unique séquentiel. Vous voudrez probablement utiliser un identifiant universellement unique à la place.

Il existe des fonctions dans la plupart des bases de données pour générer des identifiants uniques aléatoires (uuid dans mysql, postgres. newid dans mssql). Ceux-ci vous permettent de générer des données dans plusieurs bases de données, sur différentes machines, à tout moment, sans connexion réseau entre elles, tout en fusionnant les données sans aucun conflit. Cela vous permet de configurer plus facilement plusieurs serveurs et même des centres de données, comme par exemple, avec des microservices.

Cela évite également aux attaquants de deviner les URL des pages auxquelles ils ne devraient pas avoir accès. S'il y a un https://example.com/user/1263 il y a probablement un https://example.com/user/1262 ainsi que. Cela pourrait permettre l'automatisation d'un exploit de sécurité dans la page de profil utilisateur.

Il y a aussi beaucoup de cas où une colonne uuide est inutile ou même nuisible. Disons que vous avez un réseau social. Il existe une table users et une table friends. La table d'amis contient deux colonnes d'ID utilisateur et un champ d'incrémentation automatique. Tu veux 3 pour être ami avec 5, donc vous insérez 3,5 dans la base de données. La base de données ajoute un identifiant d'incrémentation automatique et stocke 1,3,5. D'une manière ou d'une autre, l'utilisateur 3 clique à nouveau sur le bouton "Ajouter un ami". Vous insérez 3,5 dans la base de données, la base de données ajoute un identifiant d'incrémentation automatique et insère 2,3,5. Mais maintenant 3 et 5 sont amis deux fois! C'est une perte d'espace, et si vous y réfléchissez, la colonne d'auto-incrémentation l'est aussi. Tout ce dont vous avez besoin pour voir si a et b sont amis est de sélectionner la ligne avec ces deux valeurs. Ils sont, ensemble, un identifiant de ligne unique. (Vous voudrez probablement écrire de la logique pour vous assurer que 3,5 et 5,3 sont dédupliqués.)

Il y a encore des cas où les identifiants séquentiels peuvent être utiles, comme lors de la construction d'un raccourcisseur d'URL, mais surtout (et même avec le raccourcisseur d'URL) un identifiant unique généré de manière aléatoire est ce que vous voulez vraiment utiliser à la place.

TL; DR: tilisez les UUID au lieu de l'incrémentation automatique, si vous ne disposez pas déjà d'un moyen unique d'identifier chaque ligne.

95
Filip Haglund

Les clés auto-cimentaires ont surtout des avantages.

Mais certains inconvénients possibles pourraient être:

  • Si vous avez une clé métier, vous devez également ajouter un index unique sur cette ou ces colonnes afin d'appliquer les règles métier.
  • Lors du transfert de données entre deux bases de données, en particulier lorsque les données sont dans plusieurs tables (c.-à-d. Maître/détail), ce n'est pas simple car les séquences ne sont pas synchronisées entre les bases de données, et vous devrez d'abord créer une table d'équivalence en utilisant le clé métier en tant que correspondance pour savoir quel ID de la base de données d'origine correspond à quel ID de la base de données cible. Cependant, cela ne devrait pas être un problème lors du transfert de données de/vers des tables isolées.
  • De nombreuses entreprises disposent d'outils de reporting ad hoc, graphiques, pointer-cliquer et glisser-déposer. Étant donné que les identifiants auto-incrémentaux n'ont aucun sens, ce type d'utilisateurs aura du mal à comprendre les données en dehors de "l'application".
  • Si vous modifiez accidentellement la clé d'entreprise, il est probable que vous ne récupérerez jamais cette ligne car vous n'avez plus quelque chose pour que les humains puissent l'identifier. Cela a causé une erreur dans la plate-forme BitCoin une fois .
  • Certains concepteurs ajoutent un ID à une table de jointure entre deux tables, alors que le PK doit simplement être composé des deux ID étrangers. De toute évidence, si la table de jointure se situe entre trois tables ou plus, un ID auto-incrémentiel est logique, mais vous devez ensuite ajouter une clé unique lorsqu'elle s'applique à la combinaison de FK pour appliquer les règles métier.

Voici une section d'article Wikipedia sur les inconvénients des clés de substitution.

61
Tulains Córdova

Juste pour être contraire, non, vous n'avez PAS besoin d'avoir toujours un PK AutoInc numérique.

Si vous analysez soigneusement vos données, vous identifiez souvent des clés naturelles dans les données. C'est souvent le cas lorsque les données ont une signification intrinsèque pour l'entreprise. Parfois, les PK sont des artefacts d'anciens systèmes que les utilisateurs professionnels utilisent comme deuxième langue pour décrire les attributs de leur système. J'ai vu des numéros de VIN de véhicule utilisés comme clé primaire d'une table "Véhicule" dans un système de gestion de flotte par exemple.

Quelle qu'en soit l'origine, SI vous avez déjà un identifiant unique, utilisez-le. Ne créez pas une deuxième clé primaire vide de sens; c'est du gaspillage et peut provoquer des erreurs.

Parfois, vous pouvez utiliser un PK AutoInc pour générer une valeur significative pour le client, par exemple Numéros de politique. Définir la valeur de départ sur quelque chose de sensé et appliquer des règles commerciales sur les zéros en tête, etc.

Lorsque vous avez un petit nombre de valeurs relativement statiques, utilisez des valeurs qui ont du sens pour l'utilisateur du système. Pourquoi utiliser 1,2,3 alors que vous pouvez utiliser L, C, H où L, H et C représentent la vie, la voiture et l'habitation dans un contexte de "type de police" d'assurance, ou, pour revenir à l'exemple VIN, que diriez-vous d'utiliser "TO "pour Toyota? Toutes les voitures Toyata ont un VIN qui commence par "TO". C'est une chose de moins à retenir pour les utilisateurs, ce qui les rend moins susceptibles d'introduire des erreurs de programmation et d'utilisateur et peut même être un substitut utilisable pour une description complète dans les rapports de gestion, ce qui simplifie les rapports. à écrire et peut-être plus rapide à générer.

Un développement ultérieur de ceci est probablement "un pont trop loin" et je ne le recommande généralement pas, mais je l'inclus pour être complet et vous pouvez en trouver une bonne utilisation. Autrement dit, utilisez la description comme clé primaire. Pour des données qui changent rapidement, c'est une abomination. Pour très données statiques signalées le All The Time, peut-être pas. Il suffit de le mentionner pour qu'il soit là comme une possibilité.

J'utilise des PK AutoInc, j'engage simplement mon cerveau et cherche d'abord de meilleures alternatives. L'art de la conception de bases de données rend quelque chose de significatif qui peut être interrogé rapidement. Avoir trop de jointures empêche cela.

EDIT Un autre cas crucial où vous n'avez pas besoin d'un PK autogénéré est le cas des tables qui représentent l'intersection de deux autres tables. Pour rester dans l'analogie avec la voiture, une voiture a 0..n accessoires, chaque accessoire peut être trouvé sur de nombreuses voitures. Donc, pour représenter cela, vous créez une table Car_Accessory contenant les PK de Car and Accessory et d'autres informations pertinentes sur le lien Dates, etc.

Ce dont vous n'avez pas (généralement) besoin est un PK AutoInc sur cette table - il ne sera accessible que via la voiture "dites-moi quels accessoires sont sur cette voiture" ou depuis l'accessoire "dites-leur quelles voitures ont cet accessoire"

20
mcottle

De nombreuses tables ont déjà un identifiant unique naturel. N'ajoutez pas une autre colonne d'ID unique (incrémentation automatique ou autre) à ces tables. Utilisez plutôt l'identifiant unique naturel. Si vous ajoutez un autre identifiant unique, vous avez essentiellement une redondance (duplication ou dépendance) dans vos données. Cela va à l'encontre des principes de normalisation. Un identifiant unique dépend de l'autre pour la précision. Cela signifie qu'ils doivent être parfaitement synchronisés à en tout temps dans chaque système qui gère ces lignes. C'est juste une autre fragilité de l'intégrité de vos données que vous ne voulez pas vraiment devoir gérer et valider à long terme.

De nos jours, la plupart des tables n'ont pas vraiment besoin de l'amélioration très mineure des performances qu'une colonne d'ID unique supplémentaire donnerait (et parfois, cela nuit même aux performances). En règle générale en informatique, évitez les redondances comme le peste! Résistez-le partout où il vous est suggéré. C'est de l'anathème. Et tenez compte de la citation. Tout devrait être aussi simple que possible, mais pas plus simple. N'ayez pas deux identifiants uniques où un suffira, même si le naturel semble moins rangé.

12
Brad Thomas

Sur les grands systèmes, l'ID est un booster de cohérence, utilisez-le presque n'importe où. Dans ce contexte, les clés primaires individuelles ne sont PAS recommandées, elles sont chères au final (lisez pourquoi).

Chaque règle a une exception, vous n'aurez donc peut-être pas besoin d'un ID d'auto-incrémentation entier sur les tables intermédiaires utilisées pour l'exportation/l'importation et sur les tables unidirectionnelles similaires ou les tables temporaires. Vous préféreriez également les GUID au lieu des ID sur les systèmes distribués.

De nombreuses réponses suggèrent que la clé unique existante devrait être prise. Eh bien, même s'il contient 150 caractères? Je ne pense pas.

Maintenant mon point principal:

Il semble que les opposants à l'ID à incrémentation automatique parlent de petites bases de données contenant jusqu'à 20 tables. Là, ils peuvent se permettre une approche individuelle de chaque table.

MAIS une fois que vous avez un ERP avec plus de 400 tables, ayant un ID d'auto-incrémentation n'importe où) (sauf les cas mentionnés ci-dessus) c'est tout à fait logique. Vous ne comptez pas sur d'autres domaines uniques, même s'ils sont présents et sécurisés pour l'unicité.

  • Vous bénéficiez d'une convention universelle de gain de temps, d'économie d'effort et facile à retenir.
  • Dans la plupart des cas, vous JOIN tables, sans avoir besoin de vérifier quelles sont les clés.
  • Vous pouvez avoir des routines de code universelles fonctionnant avec votre colonne d'auto-incrémentation d'entier.
  • Vous pouvez étendre votre système avec de nouvelles tables ou plugins utilisateurs non prévus auparavant simplement en vous référant aux identifiants des tables existantes. Ils sont déjà là depuis le début, sans frais supplémentaires.

Sur les grands systèmes, il peut être utile d'ignorer les avantages mineurs de ces clés primaires individuelles et d'utiliser systématiquement l'ID d'auto-incrémentation entière dans la plupart des cas. L'utilisation de champs uniques existants comme clés primaires permet peut-être d'économiser quelques octets par enregistrement, mais le stockage supplémentaire ou le temps d'indexation ne posent aucun problème dans les moteurs de base de données d'aujourd'hui. En fait, vous perdez beaucoup plus d'argent et de ressources sur le temps perdu des développeurs/mainteneurs. Le logiciel d'aujourd'hui devrait être optimisé pour le temps et les efforts des programmeurs - quelle approche avec des identifiants cohérents remplit mieux.

10
miroxlav

Les conceptions superflues ne sont pas une bonne pratique. C'est à dire. - il n'est pas recommandé d'avoir toujours une clé primaire à incrémentation automatique lorsque celle-ci n'est pas nécessaire.

Voyons un exemple où l'on n'est pas nécessaire.

Vous avez une table pour les articles - elle a une clé primaire int id et une colonne varchar nommée title.

Vous disposez également d'une table remplie de catégories d'articles –id clé primaire int, varchar name.

Une ligne du tableau Articles a un id sur 5 et un title "Comment faire cuire l'oie avec du beurre". Vous souhaitez lier cet article aux lignes suivantes de votre tableau Catégories: "Fowl" (id: 20), "Goose" (id: 12), "Cooking" (id: 2), "Beurre" (id: 9).

Maintenant, vous avez 2 tableaux: articles et catégories. Comment créez-vous la relation entre les deux?

Vous pourriez avoir une table avec 3 colonnes: id (clé primaire), article_id (clé étrangère), category_id (clé étrangère). Mais maintenant, vous avez quelque chose comme:

| id | a_id | c_id | 
 | 1 | 5 | 20 | 
 | 2 | 5 | 12 | 
 | 3 | 5 | 2 | 

Une meilleure solution consiste à avoir une clé primaire composée de 2 colonnes.

| a_id | c_id | 
 | 5 | 20 | 
 | 5 | 12 | 
 | 5 | 2 | 

Cela peut être accompli en faisant:

create table articles_categories (
  article_id bigint,
  category_id bigint,
  primary key (article_id, category_id)
) engine=InnoDB;

Une autre raison de ne pas utiliser un entier à incrémentation automatique est si vous utilisez des UUID pour votre clé primaire.

Les UUID sont par définition uniques, ce qui accomplit la même chose que l'utilisation d'entiers uniques. Ils ont également leurs propres avantages (et inconvénients) par rapport aux entiers. Par exemple, avec un UUID, vous savez que la chaîne unique à laquelle vous faites référence pointe vers un enregistrement de données particulier; cela est utile dans les cas où vous n'avez pas 1 base de données centrale ou lorsque les applications ont la possibilité de créer des enregistrements de données hors ligne (puis de les télécharger dans la base de données à une date ultérieure).

En fin de compte, vous ne devez pas considérer les clés primaires comme une chose. Vous devez les considérer comme la fonction qu'ils remplissent. Pourquoi avez-vous besoin de clés primaires? Pour pouvoir identifier de manière unique des ensembles spécifiques de données à partir d'une table à l'aide d'un champ qui ne sera pas modifié à l'avenir. Avez-vous besoin d'une colonne particulière appelée id pour ce faire, ou pouvez-vous baser cette identification unique sur d'autres données (immuables)?

8
anw

Une clé primaire auto-incrémentée (identité) est une bonne idée, sauf pour noter qu'elle n'a pas de sens en dehors du contexte de la base de données et des clients immédiats de cette base de données. Par exemple, si vous transférez et stockez certaines des données dans une autre base de données, puis procédez à l'écriture de données différentes dans les deux tables de base de données, les identifiants divergent - c'est-à-dire que les données avec un identifiant de 42 dans une base de données ne correspondent pas nécessairement aux données avec un identifiant de 42 dans l'autre.

Compte tenu de cela, s'il est nécessaire de pouvoir toujours identifier des lignes uniquement en dehors de la base de données (et c'est souvent le cas), vous devez avoir une clé différente à cet effet. Une clé d'entreprise soigneusement sélectionnée fera l'affaire, mais vous vous retrouverez souvent dans une position d'un grand nombre de colonnes requises pour garantir l'unicité. Une autre technique consiste à avoir une colonne Id en tant que clé primaire en cluster à incrémentation automatique et une autre colonne uniqueidentifier (guid) en tant que clé unique non en cluster, dans le but d'identifier de manière unique la ligne partout où elle existe dans le monde. La raison pour laquelle vous disposez toujours d'une clé auto-incrémentée dans ce cas est qu'il est plus efficace de regrouper et d'indexer la clé auto-incrémentée que de faire de même avec un guid.

Un cas où vous ne voudrez peut-être pas une clé d'incrémentation automatique serait une table plusieurs-à-plusieurs où la clé primaire est un composé des colonnes Id de deux autres tables (vous pourriez toujours avoir une clé d'incrémentation automatique ici, mais je n'en vois pas l'intérêt).

Une autre question concerne le type de données de la clé auto-incrémentée. L'utilisation d'un Int32 vous offre une plage de valeurs large mais relativement limitée. Personnellement, j'utilise fréquemment des colonnes bigint pour l'ID, afin de ne jamais avoir à vous soucier de manquer de valeurs.

7
MatthewToday

Ou existe-t-il des scénarios dans lesquels vous ne souhaitez pas ajouter un tel champ?

Sûr.

Tout d'abord, il existe des bases de données qui n'ont pas d'auto-incrémentations (par exemple, Oracle, qui n'est certainement pas l'un des plus petits concurrents). Cela devrait être une première indication que tout le monde ne les aime pas ou n'en a pas besoin.

Plus important, pensez à ce que l'ID est réellement est - c'est une clé primaire pour vos données. Si vous avez une table avec une clé primaire différente, vous n'avez pas besoin d'un ID et vous ne devriez pas en avoir un. Par exemple, une table (EMPLOYEE_ID, TEAM_ID) (où chaque employé peut faire partie de plusieurs équipes simultanément) a une clé primaire clairement définie composée de ces deux ID. L'ajout d'une colonne d'auto-incrémentation ID, qui est également une clé primaire pour cette table, n'aurait aucun sens. Maintenant, vous traînez 2 clés primaires, et le premier mot de la "clé primaire" devrait vous donner un indice que vous ne devriez vraiment en avoir qu'une.

7
AnoE

J'utilise généralement une colonne "identité" (entier à incrémentation automatique) lors de la définition de nouvelles tables pour des données "à longue durée de vie" (enregistrements que je m'attends à insérer une fois et à conserver indéfiniment même s'ils finissent "supprimés logiquement" en définissant un champ de bits ).

Il y a quelques situations auxquelles je peux penser lorsque vous ne voulez pas les utiliser, la plupart se résumant à des scénarios où une table sur une instance de la base de données ne peut pas être la source faisant autorité pour les nouvelles valeurs d'ID:

  • Lorsque les identifiants incrémentiels seraient trop d'informations pour un attaquant potentiel. L'utilisation d'une colonne d'identité pour les services de données "accessibles au public" vous rend vulnérable au "problème des chars allemands"; si l'enregistrement 10234 existe, il va de soi que l'enregistrement 10233, 10232, etc. existe, au moins jusqu'à l'enregistrement 10001, puis il est facile de vérifier les enregistrements 1001, 101 et 1 pour déterminer où votre colonne d'identité a commencé. Les GUID V4 composés principalement de données aléatoires brisent ce comportement incrémentiel par conception, de sorte que juste parce qu'un GUID existe, un GUID créé en incrémentant ou décrémentant un octet de le GUID n'existe pas nécessairement, ce qui rend plus difficile pour un attaquant d'utiliser un service destiné à la récupération d'un seul enregistrement comme outil de vidage. Il existe d'autres mesures de sécurité qui peuvent mieux restreindre l'accès, mais cela aide.
  • Dans les tableaux de références croisées M: M. Celui-ci est une sorte de schéma mais je l'ai déjà vu. Si vous avez une relation plusieurs-à-plusieurs entre deux tables de votre base de données, la solution de référence est une table de références croisées contenant des colonnes de clé étrangère référençant le PK de chaque table. Le PK de cette table doit pratiquement toujours être une clé composée des deux clés étrangères, pour obtenir le comportement d'index intégré et pour garantir l'unicité des références.
  • Lorsque vous prévoyez d'insérer et de supprimer en masse sur cette table beaucoup. Le plus gros inconvénient des colonnes d'identité est probablement le cadre supplémentaire que vous devez traverser lors de l'insertion de lignes d'une autre table ou requête, où vous souhaitez conserver les valeurs clés de la table d'origine. Vous devez activer "insertion d'identité" (comme cela se fait dans votre SGBD), puis vous assurer manuellement que les clés que vous insérez sont uniques, puis lorsque vous avez terminé l'importation, vous devez définir le compteur d'identité dans le les métadonnées de la table à la valeur maximale présente. Si cette opération se produit souvent sur cette table, envisagez un schéma PK différent.
  • Pour les tables distribuées. Les colonnes d'identité fonctionnent très bien pour les bases de données à instance unique, les paires de basculement et d'autres scénarios dans lesquels une instance de base de données est la seule autorité sur l'ensemble du schéma de données à un moment donné. Cependant, il n'y a que si grand que vous pouvez aller et avoir toujours un ordinateur assez rapide. La réplication ou l'envoi du journal des transactions peut vous procurer des copies supplémentaires en lecture seule, mais il y a aussi une limite à l'échelle de cette solution. Tôt ou tard, vous aurez besoin de deux ou plusieurs instances de serveur gérant les insertions de données, puis se synchronisant entre elles. Lorsque cette situation se présente, vous aurez besoin d'un champ GUID au lieu d'un champ incrémentiel, car la plupart des SGBD sont préconfigurés pour utiliser une partie des GUID qu'ils génèrent en tant qu'identifiant spécifique à l'instance, puis générez le reste de l'identifiant de manière aléatoire ou incrémentielle. Dans les deux cas, les chances d'une collision entre deux générateurs GUID sont nulles, tandis qu'une colonne de nombre entier d'identité est un cauchemar à gérer dans cette situation. (vous pouvez aller pair/impair en décalant les graines et en définissant l'incrément à 2, mais si un serveur voit plus d'activité que l'autre, vous perdez des identifiants).
  • Lorsque vous devez appliquer l'unicité sur plusieurs tables de la base de données. Il est courant dans les systèmes comptables, par exemple, de gérer le grand livre (avec une ligne pour chaque crédit ou débit de chaque compte qui s'est déjà produit) , il devient donc très gros très rapidement) sous la forme d'une séquence de tableaux représentant chacun un mois civil/année. Des vues peuvent ensuite être créées pour les connecter ensemble pour la création de rapports. Logiquement, tout cela est une très grande table, mais le découper facilite les tâches de maintenance de la base de données. Cependant, il présente le problème de la gestion des insertions dans plusieurs tables (vous permettant de commencer à enregistrer les transactions le mois suivant tout en fermant la dernière) sans se retrouver avec des clés en double. Encore une fois, les GUID au lieu des colonnes d'entier d'identité sont la solution idéale, car le SGBD est conçu pour les générer de manière vraiment unique, de sorte qu'une seule valeur GUID sera vue une seule fois) une fois dans l'ensemble du SGBD.

Il existe des solutions de contournement qui permettent d'utiliser des colonnes d'identité dans ces situations, comme je l'espère, mais dans la plupart d'entre elles, la mise à niveau de la colonne d'identité vers un GUID est plus simple et résout le problème plus complètement.

7
KeithS

Comme d'autres personnes ont plaidé pour une clé primaire incrémentielle, j'en ferai une pour un GUID:

  • Il est garanti d'être unique
  • Vous pouvez avoir un voyage de moins vers la base de données pour les données de votre application. (Pour une table de types par exemple, vous pouvez stocker le GUID dans l'application et l'utiliser pour récupérer l'enregistrement. Si vous utilisez une identité, vous devez interroger la base de données par nom et j'en ai vu beaucoup une application qui le fait pour obtenir le PK et l'interroge plus tard pour obtenir tous les détails).
  • Il est utile pour masquer des données. www.domain.com/Article/2 Me fait savoir que vous n'avez que deux articles alors que www.domain.com/article/b08a91c5-67fc-449f-8a50-ffdf2403444a ne me dit rien.
  • Vous pouvez facilement fusionner des enregistrements de différentes bases de données.
  • MSFT utilise GUIDS pour l'identité.

Modifier: Dupliquer le point

6
Three Value Logic

La question et de nombreuses réponses manquent le point important que toutes les clés naturelles pour chaque table résident uniquement dans le schéma logique pour la base de données, et toutes les clés de substitution pour chaque table résident uniquement dans le schéma physique pour la base de données. d'autres réponses discutent uniquement des avantages relatifs de l'entier par rapport à GUID clés de substitution, sans discuter des raisons pour lesquelles les clés de substitution sont correctement utilisées, et quand.

BTW: Evitons d'utiliser le terme mal défini et imprécis clé primaire. Il s'agit d'un artefact de modèles de données pré-relationnels qui a d'abord été coopté (imprudemment) dans le modèle relationnel, puis réintégré dans le domaine physique par divers fournisseurs de SGBDR. Son utilisation ne sert qu'à confondre la sémantique.

Notez du modèle relationnel que, pour que la base de données schéma logique soit dans première forme normale, chaque table doit avoir un ensemble de champs visibles par l'utilisateur, connu sous le nom de clé naturelle, qui identifie de manière unique chaque ligne de la table. Dans la plupart des cas, une telle clé naturelle est facilement identifiable, mais à l'occasion, elle doit être construite, que ce soit comme un champ tie breaker ou autrement. Cependant, une telle clé construite est toujours visible par l'utilisateur et réside donc toujours dans le schéma logique de la base de données.

En revanche, tout clé de substitution sur une table réside uniquement dans le schéma physique pour la base de données (et doit donc toujours, à la fois pour des raisons de sécurité et pour la maintenance de la base de données l'intégrité, être entièrement invisible pour les utilisateurs de la base de données). La seule raison de l'introduction d'un clé de substitution est de résoudre les problèmes de performances dans la maintenance physique et utilisation de la base de données; qu'il s'agisse de jointures, de réplication, de plusieurs sources matérielles de données ou autres.

Étant donné que la seule raison de l'introduction d'une clé de substitution est la performance, supposons que nous souhaitons qu'elle soit performante. Si le problème de performance à résoudre est lié aux jointures, nous souhaitons nécessairement rendre notre clé de substitution aussi étroite que possible (sans gêner le matériel, donc les entiers et octets courts sont généralement sortis). Les performances de jointure reposent sur une hauteur d'index minimale, donc un entier sur 4 octets est une solution naturelle. Si votre problème de performances est le taux d'insertion, un entier de 4 octets peut également être une solution naturelle (selon les internes de votre SGBDR). Si votre problème de performances pour une table est la réplication ou plusieurs sources de données que d'autres technologies clé de substitution, que ce soit une GUID ou une clé en deux parties (hôte ID + entier) peut être plus approprié. Je ne suis pas personnellement un favori des GUID mais ils sont pratiques.

Pour résumer, toutes les tables n'auront pas besoin d'une clé de substitution (de tout type); ils ne doivent être utilisés que lorsqu'ils sont jugés nécessaires à la performance du tableau considéré. Quelle que soit la technologie commune clé de substitution que vous préférez, réfléchissez bien aux besoins réels de la table avant de faire un choix; changer le clé de substitution le choix technologique pour une table sera un travail épuisant. Documentez la métrique de performance clé pour votre table afin que vos successeurs comprennent les choix effectués.

Cas spéciaux

  1. Si les exigences de votre entreprise exigent une numérotation séquentielle des transactions à des fins d'audit (ou à d'autres fins), ce champ est pas une clé de substitution; c'est une clé naturelle (avec des exigences supplémentaires). D'après la documentation, un entier auto-incrémenté ne génère que clés de substitution, alors trouvez un autre mécanisme pour le générer. Évidemment, une sorte de moniteur sera nécessaire, et si vous vous approvisionnez en transactions à partir de plusieurs sites, alors un site sera spécial, étant donné qu'il est désigné Site hôte pour le moniteur.

  2. Si votre table ne dépassera jamais une centaine de lignes, la hauteur d'index n'a pas d'importance; chaque accès se fera par un scan de table. Cependant, les comparaisons de chaînes sur des chaînes longues seront toujours beaucoup plus chères que la comparaison d'un entier de 4 octets, et plus chères que la comparaison d'un GUID.

  3. Un tableau de code valeurs saisies par un char (4) code champ doit être aussi performant que celui avec un octet de 4 octets entier. Bien que je n'en ai aucune preuve, j'utilise souvent cette hypothèse et je n'ai jamais eu de raison de la regretter.

2
Pieter Geerkens

En tant que principe de bonne conception, chaque table doit avoir un moyen fiable d'identifier de manière unique une ligne. Bien que ce soit à cela que sert une clé primaire, elle ne nécessite pas toujours l'existence d'une clé primaire. L'ajout d'une clé primaire à chaque table n'est pas une mauvaise pratique car elle permet une identification de ligne unique, mais elle peut être inutile.

Pour maintenir des relations fiables entre les lignes de deux tables ou plus, vous devez le faire via des clés étrangères, d'où la nécessité de clés primaires dans au moins certaines tables. L'ajout d'une clé primaire à chaque table facilite l'extension de la conception de votre base de données lorsque vient le temps d'ajouter de nouvelles tables ou relations aux données existantes. Planifier à l'avance est toujours une bonne chose.

En tant que principe de base (règle stricte peut-être), la valeur d'une clé primaire ne doit jamais changer pendant la durée de vie de sa ligne. Il est sage de supposer que toutes les données d'entreprise consécutives sont susceptibles de changer au cours de leur durée de vie, de sorte que toutes les données d'entreprise seront un mauvais candidat pour une clé primaire. C'est pourquoi quelque chose d'abstrait comme un entier auto-incrémenté est souvent une bonne idée. Cependant, les entiers auto-incrémentés ont leurs limites.

Si vos données n'ont qu'une vie dans votre base de données, les entiers auto-incrémentés conviennent. Mais, comme cela a été mentionné dans d'autres réponses, si vous souhaitez que vos données soient partagées, synchronisées ou qu'elles aient une vie en dehors de votre base de données, les entiers auto-incrémentés font de mauvaises clés primaires. Un meilleur choix sera un guid (aka uuid "id universellement unique").

2
Zenilogix