web-dev-qa-db-fra.com

Pourquoi les clés composites sont-elles déconseillées en veille prolongée?

Cela vient de Tutoriel officiel Hibernate :

Il existe une alternative <composite-id> déclaration qui permet d'accéder aux données héritées avec des clés composites. Son utilisation est fortement déconseillée pour autre chose.

Pourquoi les clés composites sont-elles déconseillées? J'envisage d'utiliser une table à 3 colonnes où toutes les colonnes sont des clés étrangères et forment ensemble une clé primaire qui est une relation significative dans mon modèle. Je ne vois pas pourquoi c'est une mauvaise idée, surtout que je vais utiliser un index sur eux.

Quelle est l'alternative? Créer une colonne supplémentaire générée automatiquement et l'utiliser comme clé primaire? J'ai quand même besoin d'interroger mes 3 colonnes!?

En bref, pourquoi cette affirmation est-elle vraie? et quelle est la meilleure alternative?

37
Isaac

Ils les découragent pour plusieurs raisons:

  • ils sont lourds à utiliser. Chaque fois que vous devez référencer un objet (ou une ligne), par exemple dans votre application Web, vous devez passer 3 paramètres au lieu d'un seul.
  • ils sont inefficaces. Au lieu de simplement hacher un entier, la base de données doit hacher un composite de 3 colonnes.
  • ils conduisent à des bugs: les développeurs implémentent inévitablement les méthodes equals et hashCode de la classe de clé primaire de manière incorrecte. Ou ils le rendent mutable, et modifient leur valeur une fois stockés dans un HashSet ou HashMap
  • ils polluent le schéma. Si une autre table doit faire référence à cette table à 3 colonnes, elle devra avoir 3 colonnes au lieu d'une seule en tant que clé étrangère. Supposons maintenant que vous suivez la même conception et que cette clé étrangère à 3 colonnes fasse partie de la clé primaire de cette nouvelle table, vous aurez rapidement une clé primaire à 4 colonnes, puis un PK à 5 colonnes dans le tableau suivant, etc. etc., conduisant à la duplication des données et à un schéma sale.

L'alternative est d'avoir une clé primaire à colonne unique, générée automatiquement, en plus des trois autres colonnes. Si vous souhaitez rendre unique le Tuple de trois colonnes, utilisez une contrainte unique.

44
JB Nizet

Même s'il est - peut-être - trop tard pour répondre à votre question, je veux ici donner un autre point de vue (plus modéré j'espère) sur la nécessité (est-ce vraiment un conseil?) D'Hibernate d'utiliser des clés de substitution.

Tout d'abord, je veux être clair sur le fait que les deux clés de substitution (artificielles auto-générées) et clés naturelles (composées de colonne (s ) avec une signification de domaine) ont pros et cons. Je n'essaie pas de dire qu'un type de clé est meilleur que l'autre. J'essaie de dire qu'en fonction de vos besoins, les clés naturelles peuvent être un meilleur choix que celles de substitution et vice versa.

Mythes sur les clés naturelles

  1. Les clés composites sont moins efficaces que les clés de substitution. Non! Cela dépend du moteur de base de données utilisé:
  2. Les clés naturelles n'existent pas dans la vie réelle. Désolé mais ils existent! Dans l'industrie aéronautique, par exemple, le Tuple suivant sera toujours unique en ce qui concerne un vol prévu donné (compagnie aérienne, date de départ, numéro de vol, suffixe opérationnel). Plus généralement, lorsqu'un ensemble de données d'entreprise est garanti unique par un standard donné, cet ensemble de données est un [bon] candidat clé naturel.
  3. Les clés naturelles "polluent le schéma" des tables enfants. Pour moi, c'est plus un sentiment qu'un vrai problème. Avoir une clé primaire à 4 colonnes de 2 octets chacune pourrait être plus efficace qu'une seule colonne de 11 octets. De plus, les 4 colonnes peuvent être utilisées pour interroger directement la table enfant (en utilisant les 4 colonnes dans une clause where) sans se joindre à la table parent.

Inconvénients des clés de substitution

Les clés de substitution sont:

  1. Source de problèmes de performances:
    • Ils sont généralement implémentés à l'aide de colonnes auto-incrémentées, ce qui signifie:
      • Un aller-retour à la base de données chaque fois que vous voulez obtenir un nouvel identifiant (je sais que cela peut être amélioré en utilisant des algorithmes de mise en cache ou [seq] hilo mais ces méthodes ont toujours leurs propres inconvénients).
      • Si un jour vous avez besoin de déplacer vos données d'un schéma à un autre (cela arrive au moins assez régulièrement dans mon entreprise), vous pourriez rencontrer des problèmes de collision d'ID. Et oui, je sais que vous pouvez utiliser des UUID, mais ces derniers nécessitent 32 chiffres hexadécimaux! (Si vous vous souciez de la taille de la base de données, cela peut être un problème).
      • Si vous utilisez une séquence pour toutes vos clés de substitution, vous vous retrouverez certainement avec votre base de données.
  2. Sujette aux erreurs. Une séquence a une limite max_value donc - en tant que développeur - vous devez faire attention aux faits suivants:
    • Vous devez faire défiler votre séquence (lorsque la valeur max est atteinte elle revient à 1,2, ...).
    • Si vous utilisez la séquence comme ordre (dans le temps) de vos données, vous devez gérer le cas du cyclage (la colonne avec Id 1 peut être plus récente que la ligne avec Id max-value - 1).
    • Assurez-vous que votre code (et même vos interfaces clientes qui ne devraient pas se produire car il est censé être un ID interne) prend en charge les entiers 32b/64b que vous avez utilisés pour stocker vos valeurs de séquence.
  3. Ils ne garantissent pas les données non dupliquées. Vous pouvez toujours avoir 2 lignes avec toutes les mêmes valeurs de colonne mais avec une valeur générée différente. Pour moi, c'est [~ # ~] le [~ # ~] problème des clés de substitution du point de vue de la conception de la base de données.
  4. Plus sur Wikipedia ...

Pourquoi Hibernate préfère/a besoin de clés de substitution?

Comme indiqué dans Java Persistence with Hibernate référence:

Les utilisateurs Hibernate plus expérimentés utilisent exclusivement saveOrUpdate (); il est beaucoup plus facile de laisser Hibernate décider ce qui est nouveau et ce qui est ancien, en particulier dans un réseau plus complexe d'objets à état mixte. Le seul inconvénient (pas vraiment sérieux) de saveOrUpdate () exclusif est qu'il ne peut parfois pas deviner si une instance est ancienne ou nouvelle sans lancer un SELECT sur la base de données - par exemple, lorsqu'une classe est mappée avec une clé composite naturelle et pas de propriété de version ou d'horodatage.

Certaines manifestations de la limitation (Voici comment, je pense, nous devrions l'appeler) peut être trouvée ici .

Conclusion

S'il vous plaît ne soyez pas trop au carré sur vos opinions. Utilisez des clés naturelles lorsque cela est pertinent et utilisez des clés de substitution lorsqu'il est préférable de les utiliser.

J'espère que cela a aidé quelqu'un!

39
mwnsiri

Je considérerais le problème du point de vue de la conception. Ce n'est pas seulement si Hibernate les considère comme bons ou mauvais. La vraie question est: les clés naturelles sont-elles de bons candidats pour être de bons identifiants pour mes données?

Dans votre modèle d'entreprise, il peut être pratique aujourd'hui d'identifier un enregistrement par certaines de ses données, mais les modèles d'entreprise évoluent dans le temps. Et lorsque cela se produit, vous constaterez que votre clé naturelle ne correspond plus à l'identification unique de vos données. Et avec l'intégrité référentielle dans d'autres tables, cela rendra les choses BEAUCOUP plus difficiles à changer.

Avoir un PK de substitution est pratique car il ne chaîne pas la façon dont vos données sont identifiées dans votre stockage avec votre entreprise structure du modèle .

Les clés naturelles ne peuvent pas être générées à partir d'une séquence, et le cas de données qui ne peuvent pas être identifiées par ses données est beaucoup plus fréquent. C'est la preuve que les clés naturelles diffèrent d'une clé de stockage et elles ne peuvent pas être considérées comme une approche générale (et bonne).

L'utilisation de clés de substitution simplifie la conception de l'application et de la base de données. Ils sont plus faciles à utiliser, plus performants et font un travail parfait.

Les clés naturelles n'apportent que des inconvénients: je ne vois pas un seul avantage pour l'utilisation des clés naturelles.

Cela dit, je pense que l'hibernation n'a pas vraiment de problèmes avec les clés naturelles (composées). Mais vous trouverez probablement parfois des problèmes (ou des bogues) et des problèmes avec la documentation ou en essayant d'obtenir de l'aide, car la communauté d'hibernation reconnaît largement les avantages des clés de substitution. Alors, préparez une bonne réponse pour pourquoi vous avez choisi une clé composite .

10
Luigi R. Viggiano

Si la documentation Hibernate est bien comprise:

"Il existe une alternative <composite-id> déclaration qui autorise l'accès aux données héritées avec des clés composites. Son utilisation est fortement déconseillée pour toute autre chose. "

sur le sujet 5.1.4. id tag xml <id> qui permet le mappage de clé primaire effectué trop tôt, nous pouvons conclure que la documentation hibernate décourage l'utilisation de <composite-id> au lieu de <id> balise xml pour le mappage de la clé primaire composite et ET NON rend toute référence négative pour utiliser les clés primaires composites.

1
Sinvaldo Pacheco

Les applications développées avec la base de données en tant qu'outil sont nettement plus bénéfiques pour maintenir le flux de travail sur les clés de substitution, en utilisant des indices en cluster pour l'optimisation des requêtes.

Un soin particulier doit être apporté à l'entreposage de données et aux systèmes de style OLAP cependant, qui utilisent une table de faits massive pour lier les clés de substitution des dimensions. Dans ce cas, les données dictent le tableau de bord/l'application qui peut être utilisé pour conserver des enregistrements.

Ainsi, au lieu qu'une méthode soit préférable à une autre, c'est peut-être une directive qui est avantageuse à une autre, pour la construction des clés: vous ne développerez pas une application Hibernate très facilement pour exploiter un accès direct à une instance de système SSAS.

Je développe en utilisant les deux mélanges clés, et je pense que pour mettre en œuvre un motif d'étoile solide ou de flocon de neige, un substitut avec un index cluster est généralement mon premier choix.

Donc, aux yeux de l'OP et des autres qui regardent: si vous voulez rester invariant avec votre développement (dans lequel Hibernate est spécialisé) - utilisez la méthode de substitution, et lorsque les lectures de données ont tendance à ralentir, ou vous remarquez que certaines requêtes s'épuisent performances, revenez à votre base de données spécifique et ajoutez des indices composites en cluster qui optimisent l'ordre des requêtes.

0
Nathan Teague