Clés primaires composites: est-ce bon ou mauvais
J'ai conçu une base de données pour un système de magasin en ligne. La question que j'ai rencontrée en lisant certains messages de ce site web est que même si je peux utiliser des clés primaires composites dans le cas que je vais expliquer ci-dessous, est-ce vraiment une mauvaise pratique (selon les messages que j'ai lus à cet égard sur stackoveflow, beaucoup disent que c'est une mauvaise pratique
Je veux stocker les paiements pour les commandes dans un tableau distinct. La raison en est que, un ordre peut avoir de nombreux éléments qui sont traités dans une table séparée sous la forme de plusieurs à plusieurs relation. Maintenant, si je n'utilise pas de clés primaires composites pour ma table de paiement, je perdrai mon unique PaymentID
:
[PaymentId] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[OrderId] INT NOT NULL PRIMARY KEY --Also a Foreign Key--
Maintenant, si je supprime simplement la clé primaire pour le OrderId
, je vais perdre ma relation un à un ici donc Many OrderIds can be associated to many PaymentIds
, et je ne veux pas cela.
C'est pourquoi les questions précédemment posées ici ont conclu (surtout) que la clé composite est une mauvaise idée. Donc, je veux clarifier cela pour moi-même; si c'est mauvais, Quelle est la meilleure pratique alors?
4 réponses
Il n'y a aucune conclusion que les clés primaires composites sont mauvaises.
La meilleure pratique consiste à avoir une ou plusieurs colonnes qui identifient de manière unique une ligne. Mais dans certaines tables, une seule colonne ne suffit pas à elle seule pour identifier de manière unique une ligne.
SQL (et le modèle relationnel) permet une clé primaire composite. Il est une bonne pratique est certains cas. Ou, une autre façon de le regarder est que ce n'est pas une mauvaise pratique dans tous les cas.
Certaines personnes ont l'opinion que chaque table doit avoir une colonne entière qui génère automatiquement des valeurs uniques et qui doit servir de clé primaire. Certaines personnes affirment également que cette colonne de clé primaire doit toujours être appelé id
. Mais ce sont des conventions , pas nécessairement des meilleures pratiques. Les Conventions ont un certain avantage, car elles simplifient certaines décisions. Mais les conventions sont aussi restrictives.
Vous pouvez avoir une commande avec plusieurs paiements parce que certaines personnes achat sur layaway, ou bien ils ont plusieurs sources de paiement (Deux cartes de crédit, par exemple), ou deux personnes différentes veulent payer une part de la commande (je vais souvent au restaurant avec un ami, et nous payons chacun notre propre repas, donc le personnel traite la moitié de la commande sur chacune de nos cartes de crédit).
Je concevrais le système que vous décrivez comme suit:
Products : product_id (PK)
Orders : order_id (PK)
LineItems : product_id is (FK) to Products
order_id is (FK) to Orders
(product_id, order_id) is (PK)
Payments : order_id (FK)
payment_id - ordinal for each order_id
(order_id, payment_id) is (PK)
Ceci est également lié au concept de relation d'identification . Si c'est definitional qu'un le paiement n'existe que parce qu'une commande existe, puis faites de la commande une partie de la clé primaire.
Remarque La table LineItems manque également de sa propre clé primaire à incrément automatique et à colonne unique. Plusieurs-à-plusieurs table est un exemple classique d'une bonne utilisation d'une clé primaire composite.
Cette question est dangereusement proche de demander des opinions, ce qui peut générer des guerres de religion. En tant que quelqu'un qui est très biaisé vers l'augmentation automatique des clés primaires entières dans mes tables (appelé quelque chose comme TablenameId
, pas `Id), il y a une situation où il est facultatif.
Je pense que les autres réponses expliquent pourquoi vous voulez des clés primaires.
Une raison très importante est à des fins de référence. Dans une base de données relationnelle, toute entité pourrait-en théorie - être référencée par une autre entité via des relations de clés étrangères. Pour les clés étrangères, vous voulez absolument qu'une colonne définisse une ligne de manière unique. Sinon, vous devez gérer plusieurs colonnes dans différentes tables qui s'alignent les unes avec les autres. C'est possible, mais lourd.
La table à laquelle vous faites référence n'est pas une table" entity", c'est une table" junction". C'est une construction de base de données relationnelle pour gérer les relations plusieurs à plusieurs. Parce qu'il ne représente pas vraiment une entité, il ne devrait pas avoir les relations de clé étrangère. Par conséquent, une clé primaire composite est raisonnable. Il existe certaines situations, par exemple lorsque vous êtes préoccupé par la taille de la base de données, où il est même souhaitable de laisser de côté une clé primaire artificielle.
Les meilleures pratiques concernent toujours ce qui convient le mieux à votre application. Ne regardez pas trop les "meilleures approches" arbitraires, ou vous pourriez vous retrouver avec une application pire de toute façon.
Une clé composite en SQL force la combinaison des clés incluses à être unique. Il y aurait probablement une augmentation exponentielle de la complexité pour chaque clé incluse, ce qui pourrait signifier une dégradation exponentielle des performances, en fonction de la qualité des optimisations de performances que les ingénieurs de la base de données ont pu faire. Au fur et à mesure que la table se développerait, elle se dégraderait également plus rapidement avec les clés composites.
Une diminution exponentielle des performances peut être une bonne affaire, cependant. Tant que votre table ne contiendra pas des millions de lignes, la commodité de la combinaison de touches étant toujours unique peut être justifiée. En outre, si vous avez des tables avec des millions de lignes, vous auriez probablement plus de problèmes à penser que si vos clés sont composites ou non.
Comme pour toutes les décisions techniques, c'est un l'équilibre de la loi. La dégradation des performances en vaut-elle la peine?
Une autre solution, très courante, consiste à utiliser une clé de Substitution, puis à appliquer une contrainte d'index unique aux clés qui doivent être uniques en combinaison. Cela rend les recherches dans la table moins compliquées car cela implique uniquement l'utilisation d'un index normal.
L'espace disque est bon marché, donc une clé primaire clusterisée sur une identité int(1,1) nommée d'après une convention (comme PK + nom de table) est une bonne pratique. Il rendra les requêtes, les jointures, les index et autres contraintes faciles à gérer.
Cependant, il y a une bonne raison de ne pas le faire (dans MS SQL Server au moins): si vous voulez gérer le tri physique de vos données dans le système de stockage sous-jacent.
La clé primaire en cluster détermine l'ordre de tri physique. Si vous le faites sur un colonne d'identité, l'ordre de tri physique est essentiellement l'ordre d'insertion. Cependant, cela peut ne pas être le meilleur, surtout si vous interrogez toujours la table de la même manière. Sur de très grandes tables, obtenir le bon ordre de tri physique rend les requêtes beaucoup plus rapides. Par exemple, vous pouvez vouloir l'index clusterisé sur un composite de deux colonnes.