Guide d'utilisation des clés composites pour identifier les lignes

8

Est-ce une bonne pratique (ou cela aurait-il des effets négatifs) d'utiliser un ensemble de 4 colonnes pour identifier une ligne comme étant unique (l'une étant une clé foriegn, les trois autres étant des types de données float)? J'essaie de construire une table qui (avec 4 clés liées) décrirait une entrée unique dans la table. Je suis curieux de savoir s'il s'agit d'un bon plan d'attaque ou s'il existe une meilleure solution.

À des fins visuelles, imaginez le tableau suivant. Nous avons des éléments d'inventaire qui sont organisés comme le tableau suivant: ( [K]est symbolique de la clé primaire, les lignes sont des relations)

    Sheet_Class        Sheet_Type         Sheet_Size
    ===========        ==========         ==========
[K] Sheet_Class-.  [K] Sheet_Type--.  [K] Sheet_Size
                 '---- Sheet_Class  '---- Sheet_Type
                                          Length
                                          Width
                                          Thickness

Les données peuvent se présenter de la manière suivante, mais par souci de concision, j'ai exclu de faire passer les colonnes liées:

 Sheet_Class    Sheet_Type    Sheet_Size                        (Tables)
[Sheet_Class]  [Sheet_Type]  [Length], [Width], [Thickness]     (Column Values)
=============  ============  ==============================

Aluminum
               5052-H32
                             48, 96, 0.032
                             48, 96, 0.040
                             48, 96, 0.063

               6061-T6
                             60, 120,0.032
                             60, 120,0.040
                             60, 120,0.063

Steel
               1018-CRS
                             48, 96, 0.018
                             48, 96, 0.023
                             48, 96, 0.031

En l'état (et comme je l'ai montré dans mon "schéma" ci-dessus), j'utilise une clé primaire entière simple (auto-incrémentée) pour les entrées de la table Sheet_Size . Cependant, j'aimerais savoir s'il est préférable d'utiliser une combinaison des colonnes Sheet_Type , Longueur , Largeur et Épaisseur à la place? Étant donné que chaque entrée dans Sheet_Size devrait partager toutes ces qualités uniques, et qu'un champ d'auto-incrémentation ne le démontrerait pas assez bien, est-ce la meilleure voie à suivre?

Si je n'explique pas assez bien la situation, faites-le moi savoir. Je me retrouve à avoir besoin de décomposer ces portions (classe vs type vs tailles de stock réelles) d'un matériel inventorié à d'autres fins logiques, mais je suis prêt à tout autre type de rétroaction.

Tout conseil serait apprécié.

Mise à jour (08-12-2011)

Après les réponses affichées, j'ai décidé de faire une combinaison de la réponse de Mark & la réponse de X-Zero . J'ai décidé que c'était une bonne idée de placer une contrainte unique sur les colonnes de longueur, largeur et épaisseur, mais j'aime aussi l'idée de décomposer les tailles de matériaux en lignes uniques et de les lier à une relation.

Malheureusement, je ne peux pas accepter les deux réponses, donc je vais accepter X-Zeros pour avoir (ce que je ressens) un regard plus critique sur le problème et offrir un ajustement du schéma.

Merci à tous pour vos réponses.

Brad Christie
la source

Réponses:

6

Après y avoir réfléchi, je réviserais légèrement la structure de votre table.
Tout d'abord, révisez votre tableau de taille de feuille:

Sheet_size
===========
Id
Length
Width
Thickness

Deuxièmement, créez une table de relation taille / type de feuille:

Sheet_size_type
================
Sheet_Type_Id
Sheet_Size_Id

Créez ensuite les contraintes suivantes:

  1. La clé primaire (et l'index) de Sheet_sizedoit être la colonne id
  2. Il devrait y avoir une sorte de clé (et d'index) unique appliquée aux dimensions dans Sheet_size. Considérez, deux feuilles de dimensions (48, 96, 0,5) et (96, 48, 0,5) sont-elles égales (c'est-à-dire, la direction des dimensions est-elle importante)? Ce type de problème peut être difficile à appliquer si vous utilisez les colonnes dans le cadre de la clé primaire, mais devient plus gérable lorsque vous utilisez des contraintes et des procédures stockées.
  3. La clé primaire (et l'index) de Sheet_size_typedoit utiliser les deux clés étrangères, en commençant par celle avec la cardinalité la plus basse (probablement sheet_type, selon votre exemple). Vous voudrez peut-être un index supplémentaire dans l'autre sens, mais il peut ne pas être nécessaire.

Cette révision vous permettra d'économiser de l'espace dans la base de données (en proportion du nombre de types de feuilles utilisant la même taille) et ne devrait pas trop affecter les frais généraux.


Il existe d'autres problèmes potentiels concernant l'égalité / l'unicité si vous utilisez un floattype de données, car l'imprécision peut vous déclencher de manière inattendue. Vous devez déterminer si un type à virgule fixe, avec une précision donnée, serait plus approprié.

Clockwork-Muse
la source
J'avais l'intention de limiter la longueur et la largeur à une seule (deux possibles) décimales, et l'épaisseur s'étendrait (au plus) à trois. Au-delà de cela, nous devenons trop finis (et le stock lui-même n'entre jamais dans les chiffres décrits de toute façon). Cela mis à part, j'aime l'idée de diviser les tailles de feuilles, mais le problème auquel je suis confronté sont les autres colonnes impliquées (que j'ai exclues). (besoin de plus de place, voir le post suivant)
Brad Christie
Comme il s'agit d'une liste de stock inventorié, je dois inclure d'autres informations telles que la densité et le coût / lb (qui est fortement basé sur le type (et même l'épaisseur. Par exemple, "Acier" / "1018" pourrait être de 0,55 $ / lb) à 0,018-0,125 "d'épaisseur, mais devient 0,65 $ / lb une fois que l'épaisseur dépasse 0,125" (et cela peut également différer entre une taille de feuille de 48 "x96" x0,250 "de 1018 contre 5052-H32). Dans votre exemple, Je n'aurais qu'une seule entrée pour un 48 "x96" x0.125 "(bien que je suppose que la table des relations pourrait avoir ces mesures supplémentaires)
Brad Christie
Si vous n'avez besoin que d'un petit nombre de décimales, alors oui, utilisez une précision fixe. Oui, c'est là (dans ce cas) que vous mettriez des informations comme ça (le coût dépend du type et de la taille de la feuille, par exemple), bien que vous souhaitiez peut-être générer des tableaux supplémentaires pouvant être référencés. Vous pouvez également envisager de créer des types de données personnalisés (comme la densité) afin que les utilisateurs n'essaient pas d'interroger vos données de manière inattendue.
Clockwork-Muse
6

On dirait une décision clé naturelle vs substitut , une opinion sur laquelle va de réfléchi et pratique à académique , à la limite du dogme. Selon le SGBDR, il existe des considérations pour le modèle physique qui peuvent avoir des implications importantes sur les performances, par exemple le choix de la clé en cluster dans SQL Server.

Personnellement, si j'ai une clé candidate à attribut étroit et unique, je suis tenté de l'utiliser. Touches larges et / ou composites, par défaut j'ajoute un substitut au modèle. Dans votre cas, je voterais pour la colonne d'identité sur Sheet_Size en tant que clé principale en cluster et une contrainte unique sur le type / longueur / largeur / épaisseur.

Mark Storey-Smith
la source
Mais étant donné que vous avez maintenant une clé "arbitraire" donnée à la ligne, comment unique impose-t-il que les colonnes (lorsqu'elles sont combinées) ne peuvent pas avoir de valeurs en double? Je crois comprendre que l'attribut unique se rapporte à la clé. Vous vous dites Sheet_Size INT PRIMARY KEYet Length UNIQUE, Width UNIQUE, Thickness UNIQUE? Je ne comprends toujours pas comment cela empêche les doublons dans la table (sans appliquer de logique à l'interface d'insertion). (Peut-être que je manque quelque chose?)
Brad Christie
Une contrainte unique sur les trois colonnes: ALTER TABLE dbo.Sheet_Size ADD CONSTRAINT UC_LengthWidthThickness UNIQUE ([Longueur], [Largeur], [Épaisseur])
Mark Storey-Smith
Merci pour votre retour. Je suis d'accord qu'une contrainte unique sur les colonnes serait une excellente solution, mais j'aime aussi la recommandation de X-Zero de diviser les tailles en une nouvelle table (liée à une nouvelle table). Donc, pour combiner des idées, j'appliquerai la contrainte unique à la table de taille "Stripped-down", tout en supprimant les informations de densité et de coût / lb et en les plaçant dans la table des relations.
Brad Christie
4

Je vais vous rediriger un peu vers cette réponse d'une question précédente .

Citation: "En ce qui concerne la façon de concevoir cette clé primaire, il existe deux écoles de pensée:

  • celle qui fait du PK une colonne distincte, généralement auto-générée, comme un GUID ou et incrémentation automatique INT (dans votre cas, une colonne unique unique d'identification);
  • celui qui rend le PK en tant que colonne (ou ensemble de colonnes) interne à la table (dans votre cas, serait un nom d'utilisateur ou un e-mail ou SSN, tout ce qui rend cet utilisateur unique) qui identifie de manière unique un enregistrement.

À quelle ligne vous adhérez, ce n'est qu'une question de goût. "

Les effets secondaires de toute solution choisie pourraient être:

  • L'utilisation de clés composées partout:

    • augmenter le stockage pour toutes les tables impliquées;
    • augmenter / compliquer les index sur les FK souvent utilisés;
    • complique un peu l'écriture de toutes vos déclarations de jointure
    • rendre M. Joe Celko heureux :-) (des références sur ses opinions concernant les clés naturelles ou artificielles peuvent être trouvées ici et ici , et surtout partout où il est interrogé sur la question)
  • l'utilisation des clés générées:

    • simplifier les 3 étapes précédentes
    • compliquer la situation de réplication d'une table avec l'identité PK (références ici , ici ou ici )

Personnellement, je préfère les clés INT IDENTITY générées, mais ce qui vous convient devrait bien.

Marian
la source
2

La clé composite est parfaitement logique. L'implémentation de cette clé garantit que les attributs métier ne peuvent pas être dupliqués. C'est une bonne chose car enregistrer plusieurs fois les mêmes données entraînerait une ambiguïté, des dépendances indésirables et rendrait plus probable les erreurs utilisateur et les données incorrectes.

La clé d'incrémentation automatique seule ne protégera pas l'intégrité de vos données d'entreprise. Si la clé d'incrémentation automatique ne sert aucun objectif particulier (par exemple en tant que cible d'une référence de clé étrangère dans une autre table), elle peut être supprimée en toute sécurité.

nvogel
la source
... Sauf en supprimant l'incrémentation automatique car la clé étrangère nécessiterait d'utiliser toutes les colonnes de dimension dans le cadre de la clé étrangère (c'est-à-dire les quatre colonnes , en incluant le type). Pas quelque chose que je veux comme clé étrangère, point - colonnes simples seulement, s'il vous plaît. Je suis d'accord que c'est une bonne idée de mettre une clé unique (et / ou vérifier la contrainte) sur les dimensions (et le type, selon la conception de la table).
Clockwork-Muse
@ X-Zero, j'ai fait le point sur les références de clés étrangères dans mon deuxième paragraphe. La question que j'ai lue est de savoir s'il faut implémenter la clé composite, et non s'il faut également avoir une incrémentation automatique.
nvogel