web-dev-qa-db-fra.com

Clés primaires composites: est-ce bon ou mauvais

J'ai conçu une base de données pour un système de boutique en ligne. La question que j'ai rencontré en lisant certains articles sur ce site 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, c'est pourquoi je demande).

Je souhaite enregistrer les paiements des commandes dans une table distincte. La raison en est qu'une commande peut avoir de nombreux articles qui sont traités dans une table distincte sous la forme d'une relation plusieurs à plusieurs. Maintenant, si je n'utilise pas de clés primaires composites pour ma table de paiement, je perdrai mon PaymentID unique:

[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 du OrderId, je perdrai ma relation un à un ici, donc Many OrderIds can be associated to many PaymentIds, et je ne veux pas ça.

C'est pourquoi les questions précédemment posées ici ont conclu (principalement) que la clé composite est une mauvaise idée. Je veux donc clarifier cela par moi-même; si c'est mauvais, quelle est la meilleure pratique alors?

42
JAX

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 certains tableaux, une seule colonne ne suffit pas à elle seule pour identifier une ligne de manière unique.

SQL (et le modèle relationnel) autorise une clé primaire composite. C'est une bonne pratique dans certains cas. Ou, une autre façon de voir les choses est que ce n'est pas une mauvaise pratique dans tous les cas.

Certaines personnes pensent que chaque table devrait avoir une colonne entière qui génère automatiquement des valeurs uniques, et qui devrait servir de clé primaire. Certaines personnes affirment également que cette colonne de clé primaire doit toujours être appelée id. Mais ce sont conventions , pas nécessairement les meilleures pratiques. Les conventions présentent certains avantages, car elles simplifient certaines décisions. Mais les conventions sont également restrictives.

Vous pouvez avoir une commande avec plusieurs paiements parce que certaines personnes achètent en cas de mise de côté , ou bien elles 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 pour notre propre repas, donc le personnel traite la moitié de la commande sur chacune de nos cartes de crédit).

Je voudrais concevoir 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 . S'il est définitif qu'un paiement existe uniquement parce qu'une commande existe, alors faites-la partie de la clé primaire.

Notez que la table LineItems n'a pas non plus sa propre clé primaire à auto-incrémentation sur une seule colonne. Une table plusieurs-à-plusieurs est un exemple classique d'une bonne utilisation d'une clé primaire composite.

45
Bill Karwin

Cette question est dangereusement proche de demander des opinions, ce qui peut générer des guerres de religion. En tant que personne très biaisée pour avoir des clés primaires entières à augmentation automatique dans mes tables (appelées quelque chose comme TablenameId, pas Id), il y a une situation où c'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é étrangère. Pour les clés étrangères, vous voulez certainement qu'une colonne définisse de manière unique une ligne. Sinon, vous devez gérer plusieurs colonnes dans des tables différentes qui s'alignent les unes sur les autres. C'est possible, mais lourd.

La table à laquelle vous faites référence n'est pas une table "entité", c'est une table "jonction". Il s'agit d'une construction de base de données relationnelle pour gérer les relations plusieurs-à-plusieurs. Parce qu'elle ne représente pas vraiment une entité, elle ne doit pas avoir de relations de clé étrangère. Par conséquent, une clé primaire composite est raisonnable. Dans certaines situations, par exemple lorsque vous êtes préoccupé par la taille de la base de données, il peut même être souhaitable de supprimer une clé primaire artificielle.

19
Gordon Linoff

L'espace disque étant bon marché, une clé primaire en cluster 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, jointures, index et autres contraintes faciles à gérer.

Cependant, il y a une bonne raison de ne pas le faire (au moins dans MS SQL Server): si vous souhaitez 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 une 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 accélère considérablement les requêtes. Par exemple, vous souhaiterez peut-être l'index cluster sur un composite de deux colonnes.

7
JeromeE

Les meilleures pratiques sont utiles au mieux, mais aveuglantes au pire. Aller à l'encontre d'une meilleure pratique n'est pas un péché. Assurez-vous simplement de savoir quel type de compromis vous faites.

Les moteurs de base de données peuvent être des choses très compliquées. Sans savoir quelles optimisations particulières sont faites par un moteur donné, il sera difficile de déterminer quels types de constructions donneront les meilleures performances (car je suppose que le problème dont nous parlons ici est la performance). Les clés composites peuvent être problématiques pour les grandes tables dans un type de base de données, mais n'ont pas d'impact notable sur un autre.

Une pratique utile que j'ai apprise est de toujours s'efforcer d'avoir mes applications aussi simples que possible. L'utilisation de clés composites vous évite-t-elle d'avoir à effectuer des recherches avant les insertions ou d'autres nuisances? Utilise les. Cependant, si vous remarquez que leur utilisation fait que votre application ne satisfait plus à certaines exigences de performances importantes, envisagez une solution sans eux.

5
Emanuel