web-dev-qa-db-fra.com

Y a-t-il un moment où l'utilisation d'une relation base de données 1: 1 est logique?

L’autre jour, je pensais à la normalisation, et j’ai eu l’impression que je ne pouvais penser à un moment où il devrait y avoir une relation 1: 1 dans une base de données.

Nom: SSN? Je les aurais dans le même tableau PersonID: AddressID? Encore une fois, même table.

Je peux trouver des zillions d’exemples 1: plusieurs ou plusieurs: beaucoup (avec des tables intermédiaires appropriées), mais jamais un 1: 1.

Est-ce que je manque quelque chose d'évident?

145
Pulsehead

Une relation 1: 1 indique généralement que vous avez partitionné une entité plus grande pour une raison quelconque. C’est souvent pour des raisons de performances dans le schéma physique, mais cela peut aussi se produire du côté logique si une grande partie des données est supposée être "inconnue" en même temps (auquel cas vous avez un rapport 1: 0). ou 1: 1, mais pas plus).

Exemple de partition logique: vous avez des données sur un employé, mais vous devez collecter un plus grand ensemble de données, si et seulement si elles choisissent d'avoir une couverture santé. Je garderais les données démographiques concernant la couverture santé dans un tableau différent pour faciliter le partitionnement de la sécurité et éviter de transporter ces données dans des requêtes sans rapport avec l'assurance.

Un exemple de partition physique serait les mêmes données hébergées sur plusieurs serveurs. Je peux conserver les données démographiques de la couverture santé dans un autre État (où se trouve le bureau des ressources humaines, par exemple) et la base de données primaire peut uniquement y être reliée via un serveur lié ... en évitant de répliquer des données sensibles vers d'autres endroits, tout en les rendant disponibles (en supposant ici rare) les requêtes qui en ont besoin.

Le partitionnement physique peut être utile à chaque fois vous avez des requêtes qui nécessitent des sous-ensembles cohérents d'une entité plus grande.

144
Godeke

Une des raisons est l'efficacité de la base de données. Avoir une relation 1: 1 vous permet de diviser les champs qui seront affectés lors d’un verrou de ligne/table. Si le tableau A contient une tonne de mises à jour et que le tableau b contient une tonne de lectures (ou contient une tonne de mises à jour d'une autre application), le verrouillage du tableau A n'aura aucune incidence sur ce qui se passe dans le tableau B.

D'autres soulèvent un bon point. La sécurité peut également être une bonne raison en fonction de la manière dont les applications, etc., atteignent le système. J'aurais tendance à adopter une approche différente, mais cela peut être un moyen facile de restreindre l'accès à certaines données. Il est très facile de refuser l'accès à une table donnée.

Mon entrée de blog à ce sujet.

114
kemiller2002

La maigreur. La relation de données peut être techniquement de 1: 1, mais les lignes correspondantes ne doivent pas exister pour chaque ligne. Ainsi, si vous avez vingt millions de lignes et qu'il existe un ensemble de valeurs qui n'existe que pour 0,5% d'entre elles, les économies d'espace sont considérables si vous insérez ces colonnes dans un tableau pouvant être peu rempli.

39
chaos

La plupart des réponses très bien classées donnent des raisons très utiles d'optimisation et d'optimisation de la base de données pour les relations 1: 1, mais je souhaite me concentrer sur des exemples "à l'état sauvage" dans lesquels des relations 1: 1 se produisent naturellement.

Veuillez noter une caractéristique importante de l'implémentation de la base de données dans la plupart de ces exemples: aucune information historique n'est conservée concernant la relation 1: 1. C'est-à-dire que ces relations sont 1: 1 à un moment donné. Si le concepteur de la base de données souhaite enregistrer les changements intervenus dans la relation entre les participants au fil du temps, les relations deviennent alors 1: M ou M: M; ils perdent leur nature 1: 1. Avec cela compris, voici:

  • Relations de type "Est-A" ou supertype/sous-type ou héritage/classification : Cette catégorie correspond au moment où une entité est un type spécifique d'une autre entité. Par exemple, il peut exister une entité Employé avec des attributs qui s'appliquent à tous les employés, puis différentes entités pour indiquer des types spécifiques d'employé avec des attributs uniques pour ce type d'employé, par exemple. Docteur, Comptable, Pilote, etc. Cette conception évite les valeurs nulles car de nombreux employés n'auraient pas les attributs spécialisés d'un sous-type spécifique. Les autres exemples de cette catégorie pourraient être Product en tant que supertype, et ManufacturingProduct et MaintenanceSupply en tant que sous-types; Animal comme supertype et Dog and Cat comme sous-types; etc. Notez que chaque fois que vous essayez de mapper une hiérarchie d'héritage orientée objet dans une base de données relationnelle (telle que dans un modèle relationnel objet), il s'agit du type de relation qui représente de tels scénarios.

  • Relations de "boss" , telles que directeur, président, président, etc., lorsqu'une unité organisationnelle ne peut avoir qu'un seul patron et qu'une personne ne peut être le patron d'une seule unité d'organisation. Si ces règles s'appliquent, vous avez alors une relation 1: 1, telle qu'un directeur de département, un directeur général d'une entreprise, etc. Les relations de "patron" ne s'appliquent pas uniquement aux personnes. Le même type de relation existe s'il n'y a qu'un seul magasin comme siège d'une entreprise ou si une seule ville est la capitale d'un pays, par exemple.

  • Quelques types d’allocation de ressources rares , par ex. Un employé ne peut être affecté qu’à un véhicule de société à la fois (par exemple, un camion par camionneur, un taxi par chauffeur de taxi, etc.). Un collègue m'a donné cet exemple récemment.

  • Mariage (au moins dans les juridictions où la polygamie est illégale): une personne ne peut être mariée qu'à une autre personne à la fois. J'ai trouvé cet exemple dans un manuel qui l'utilisait comme exemple d'une relation unaire 1: 1 lorsqu'une entreprise enregistre les mariages entre ses employés.

  • Réservations correspondantes : lorsqu'une réservation unique est effectuée, puis remplie en deux entités distinctes. Par exemple, un système de location de voiture peut enregistrer une réservation dans une entité, puis une location réelle dans une entité distincte. Bien qu'une telle situation puisse également être conçue comme une entité unique, il peut être judicieux de séparer les entités car toutes les réservations ne sont pas remplies et toutes les locations ne nécessitent pas de réservation, et les deux situations sont très courantes.

Je répète l'avertissement que j'ai déjà fait, à savoir que la plupart de ces relations sont des relations 1: 1 uniquement si aucune information historique n'est enregistrée. Ainsi, si un employé change de rôle dans une organisation, si un responsable assume la responsabilité d'un autre département, ou si un employé se voit réaffecter un véhicule, ou si une personne est veuve et se remarie, la relation des participants peut alors changer. Si la base de données ne stocke aucun historique antérieur concernant ces relations 1: 1, elles restent alors légitimes. Toutefois, si la base de données enregistre des informations historiques (telles que l’ajout de dates de début et de fin pour chaque relation), elles se transforment en relations M: M.

La note historique comporte deux exceptions notables. Premièrement, certaines relations changent si rarement que des informations historiques ne seraient normalement pas stockées. Par exemple, la plupart des relations IS-A (par exemple, le type de produit) sont immuables; c'est-à-dire qu'ils ne peuvent jamais changer. Ainsi, le point d'enregistrement historique est sans objet; ceux-ci seraient toujours implémentés comme des relations naturelles 1: 1. Deuxièmement, le magasin de relations de réservation et de location date séparément, car la réservation et la location sont des événements indépendants, chacun ayant ses propres dates. Étant donné que les entités ont leurs propres dates, plutôt que la relation 1: 1 ayant elle-même une date de début, celles-ci resteraient sous la forme de relations 1: 1 même si des informations historiques sont stockées.

22
Tripartio

Votre question peut être interprétée de plusieurs façons, à cause de la façon dont vous l'avez formulée. Les réponses montrent cela.

Il peut certainement y avoir des relations 1: 1 entre des éléments de données dans le monde réel. Aucune question à ce sujet. La relation "est un" est généralement un à un. Une voiture est un véhicule ... Une voiture est un véhicule. Un véhicule peut être une voiture. Certains véhicules sont des camions, auquel cas un véhicule n'est pas une voiture. Plusieurs réponses abordent cette interprétation.

Mais je pense que ce que vous demandez vraiment, c’est ... quand les relations 1: 1 existent, les tables doivent-elles être divisées? En d'autres termes, devriez-vous avoir deux tables contenant exactement les mêmes clés? En pratique, la plupart d’entre nous n’analysons que les clés primaires, et non les autres clés candidates, mais cette question est légèrement différente.

Les règles de normalisation pour 1NF, 2NF et 3NF ne nécessitent jamais de décomposer (fractionner) une table en deux tables avec la même clé primaire. Je n'ai pas compris si le fait de placer un schéma dans BCNF, 4NF ou 5NF pouvait entraîner la création de deux tables avec les mêmes clés. De mémoire, je vais deviner que la réponse est non.

Il existe un niveau de normalisation appelé 6NF. La règle de normalisation pour 6NF peut définitivement générer deux tables avec la même clé primaire. 6NF a l'avantage sur 5NF que NULLS peut être complètement évité. Ceci est important pour certains concepteurs de bases de données, mais pas tous. Je n'ai jamais pris la peine de mettre un schéma en 6NF. 

Dans 6NF, les données manquantes peuvent être représentées par une ligne omise, au lieu d'une ligne avec une valeur NULL dans une colonne. 

Il y a des raisons autres que la normalisation pour diviser les tables. Parfois, les tables divisées améliorent les performances. Avec certains moteurs de base de données, vous pouvez obtenir les mêmes avantages en termes de performances en partitionnant la table au lieu de la diviser. Cela peut avoir l’avantage de garder la conception logique facile à comprendre, tout en donnant au moteur de base de données les outils nécessaires pour accélérer les choses. 

21
Walter Mitty

Je les utilise principalement pour plusieurs raisons. L'une est la différence significative dans le taux de changement de données. Certaines de mes tables peuvent avoir des traces d'audit dans lesquelles je dépiste les versions précédentes des enregistrements. Si je me soucie seulement de suivre les versions précédentes de 5 colonnes sur 10, diviser ces 5 colonnes en une table séparée avec un mécanisme de trace d'audit est plus efficace. De plus, il se peut que des enregistrements (par exemple pour une application de comptabilité) soient en écriture uniquement. Vous ne pouvez pas modifier les montants en dollars, ni le compte auquel ils étaient destinés. Si vous avez commis une erreur, vous devez créer un enregistrement correspondant pour corriger les erreurs, puis créer une entrée de correction. La table est soumise à des contraintes imposant le fait qu’elles ne peuvent pas être mises à jour ou supprimées, mais j’ai peut-être deux attributs malléables pour cet objet; ceux-ci sont conservés dans un tableau séparé sans la restriction de modification. Une autre fois que je fais cela est dans les applications de dossiers médicaux. Certaines données relatives à une visite ne peuvent plus être modifiées une fois la signature validée, et d'autres données relatives à une visite pouvant être modifiées après la signature. Dans ce cas, je vais scinder les données et placer un déclencheur sur la table verrouillée, en rejetant les mises à jour de la table verrouillée lors de la signature, mais en autorisant les mises à jour des données non approuvées par le médecin.

Une autre affiche expliquant que 1: 1 n’était pas normalisé, je ne suis pas d’accord avec cela dans certaines situations, notamment en ce qui concerne le sous-typage. Supposons que j'ai une table d'employés et que la clé primaire est leur SSN (c'est un exemple, sauvegardons le débat sur le fait de savoir s'il s'agit d'une bonne clé ou non pour un autre thread). Les employés peuvent être de différents types, temporaires ou permanents, et s’ils sont permanents, ils doivent remplir un plus grand nombre de champs, comme le numéro de téléphone du bureau, qui ne devrait être nul si le type = 'Permanent'. Dans une 3ème base de données de forme normale, la colonne ne devrait dépendre que de la clé, c'est-à-dire de l'employé, mais cela dépend en fait de l'employé et du type. Une relation 1: 1 est donc tout à fait normale et souhaitable dans ce cas. Cela évite aussi les tables trop rares, si j'ai 10 colonnes normalement remplies, mais 20 colonnes supplémentaires uniquement pour certains types.

19
Shane Delmore

Le scénario le plus courant auquel je peux penser est lorsque vous avez un BLOB. Supposons que vous souhaitiez stocker des images volumineuses dans une base de données (ce n'est généralement pas la meilleure façon de les stocker, mais les contraintes le rendent parfois plus pratique). En règle générale, vous voudriez que le blob se trouve dans un tableau séparé afin d'améliorer la recherche des données non-blob. 

13
Erik Funkenbusch

En termes de science pure, oui, ils sont inutiles.

Dans les bases de données réelles, il est parfois utile de conserver un champ rarement utilisé dans une table séparée: pour accélérer les requêtes en utilisant ce champ et uniquement ce champ; pour éviter les serrures, etc.

9
Quassnoi

Des relations 1-1 sont également nécessaires si vous avez trop d'informations. Il existe une limite de taille d'enregistrement pour chaque enregistrement de la table. Parfois, les tables sont divisées en deux (avec les informations les plus fréquemment interrogées dans la table principale) afin que la taille de l'enregistrement ne soit pas trop grande. Les bases de données sont également plus efficaces pour interroger si les tables sont étroites. 

8
HLGEM

Plutôt que d’utiliser des vues pour restreindre l’accès aux champs, il est parfois judicieux de conserver les champs restreints dans une table séparée à laquelle seuls certains utilisateurs ont accès.

8
eleven81

Je peux également penser aux situations dans lesquelles vous utilisez un modèle OO dans lequel vous utilisez l'héritage, et où l'arbre de l'héritage doit être conservé dans la base de données.

Par exemple, vous avez une classe Bird et Fish qui héritent toutes les deux de Animal . Dans votre DB, vous pouvez avoir une table 'Animal', qui contient les champs communs de la classe Animal -une relation avec la table Bird et une relation individuelle avec la table Fish.

Dans ce cas, vous n'avez pas besoin d'une table Animal contenant un grand nombre de colonnes nullable pour contenir les propriétés Bird et Fish, où toutes les colonnes contenant des données Fish sont définies sur NULL lorsque l'enregistrement représente un oiseau. 

Au lieu de cela, vous avez un enregistrement dans la table Birds qui a une relation un-à-un avec l'enregistrement dans la table Animal.

8
Frederik Gheysels

C'est aussi un moyen d'étendre une table qui est déjà en production avec moins de risque (perçu) qu'un "vrai" changement de base de données. Voir une relation 1: 1 dans un système existant est souvent un bon indicateur que des champs ont été ajoutés après la conception initiale.

5
J.T. Grimes

En SQL, il est impossible d'appliquer une relation 1: 1 entre deux tables obligatoire des deux côtés (sauf si les tables sont en lecture seule). Dans la plupart des cas, une relation "1: 1" en SQL signifie réellement 1: 0 | 1.

L'incapacité à prendre en charge la cardinalité obligatoire dans les contraintes référentielles est l'une des sérieuses limitations de SQL. Les contraintes "reportables" ne comptent pas vraiment parce qu'elles ne sont qu'une façon de dire que la contrainte n'est pas forcée de temps en temps.

5
nvogel

Si vous utilisez les données avec l'un des ORM les plus répandus, vous pouvez diviser une table en plusieurs tables correspondant à votre hiérarchie d'objets.

4
Jason Punyon

J'ai constaté que lorsque je fais une relation 1: 1, c'est totalement pour une raison systémique, pas une raison relationnelle.

Par exemple, j'ai constaté que le fait de placer les aspects réservés d'un utilisateur dans une table et de placer ses champs modifiables dans une autre table permet d'écrire de manière logique ces règles sur les autorisations sur ces champs beaucoup plus facilement.

Mais vous avez raison, en théorie, les relations 1: 1 sont complètement artificielles et constituent presque un phénomène. Cependant, cela facilite logiquement les programmes et les optimisations permettant de résumer la base de données.

4
DevelopingChris

La plupart du temps, on pense que les motifs sont 1: 1 jusqu'à ce que quelqu'un demande "bon, pourquoi ne peut-il pas s'agir de 1: plusieurs"? La séparation prématurée des concepts les uns des autres est effectuée en prévision de ce scénario courant. Personne et adresse ne sont pas si étroitement liés. Beaucoup de gens ont plusieurs adresses. Etc...

Habituellement, deux espaces objets distincts impliquent qu'un ou les deux peuvent être multipliés (x: plusieurs). Si deux objets étaient vraiment, vraiment 1: 1, même philosophiquement, c'est plutôt une relation de type «is-relation». Ces deux "objets" sont en réalité des parties d'un objet entier.

4
Mark Canlas

informations étendues qui ne sont nécessaires que dans certains scénarios. dans les anciennes applications et les langages de programmation (tels que RPG) où les programmes sont compilés sur les tables (ainsi, si la table change, vous devez recompiler le ou les programmes). Marquer le long des fichiers peut également être utile dans les cas où vous devez vous soucier de la taille de la table.

3
Ryan Guill

La meilleure raison pour laquelle je vois une relation 1: 1 est un sous-type SuperType de la conception de la base de données. J'ai créé une structure de données Real Estate MLS basée sur ce modèle. Il y avait cinq différents flux de données; Résidentiel, Commercial, Multifamilial, Hôtels et terrains.

J'ai créé une propriété appelée SuperType contenant des données communes à chacun des cinq flux de données distincts. Cela permettait des recherches "simples" très rapides dans tous les types de données. 

Je crée cinq sous-types distincts qui stockent les éléments de données uniques pour chacun des cinq flux de données. Chaque enregistrement SuperType avait une relation 1: 1 avec l'enregistrement de sous-type approprié.

Si un client souhaite une recherche détaillée, il doit sélectionner un type Super-Sub, par exemple PropertyResidential. 

Le plus souvent, il s'agit davantage d'une construction physique que logique. Il est généralement utilisé pour partitionner verticalement une table afin de tirer parti de la scission d'E/S sur des périphériques physiques ou d'autres optimisations de requête associées à la séparation des données moins fréquemment consultées ou devant être gardées plus sécurisées que le reste des attributs du même objet (SSN, Salary, etc).

La seule considération logique qui prescrit une relation 1-1 est lorsque certains attributs ne s'appliquent qu'à certaines entités. Cependant, dans la plupart des cas, il existe un moyen plus simple/mieux normalisé de modéliser les données via l'extraction d'entités.

2
JohnFx

À mon avis, une relation 1: 1 mappe un héritage de classe sur un SGBDR. Il existe une table A contenant les attributs communs, c’est-à-dire le statut de la classe de partent. attributs spécialisés . La table namend A contient également un champ "type" qui représente la fonctionnalité "transtypage"

Au revoir Mario

1
Mario

C'est inutile super pour des raisons de sécurité, mais il existe de meilleurs moyens d'effectuer des contrôles de sécurité. Imaginez, vous créez une clé qui ne peut ouvrir qu’une seule porte. Si la clé peut ouvrir une autre porte, vous devriez sonner l'alarme. En substance, vous pouvez avoir "CitizenTable" et "VotingTable". Citoyen Un vote pour le candidat un qui est stocké dans la table de vote. Si un citoyen apparaît à nouveau sur la table de vote, il devrait alors déclencher une alarme. Soyez conseil, il s'agit d'une relation un à un car nous ne faisons pas référence au champ candidat, nous nous référons à la table de vote et à la table des citoyens. 

Exemple:

 Citizen Table
 id = 1, citizen_name = "EvryBod"
 id = 2, citizen_name = "Lesly"
 id = 3, citizen_name = "Wasserman"

 Candidate Table
 id = 1, citizen_id = 1, candidate_name = "Bern Nie"
 id = 2, citizen_id = 2, candidate_name = "Bern Nie"
 id = 3, citizen_id = 3, candidate_name = "Hill Arry"

Ensuite, si nous voyons la table de vote comme telle: 

 Voting Table
 id = 1, citizen_id = 1, candidate_name = "Bern Nie"
 id = 2, citizen_id = 2, candidate_name = "Bern Nie"
 id = 3, citizen_id = 3, candidate_name = "Hill Arry"
 id = 4, citizen_id = 3, candidate_name = "Hill Arry"
 id = 5, citizen_id = 3, candidate_name = "Hill Arry"

On pourrait dire que le citoyen numéro 3 est un menteur en feu qui a trompé Bern Nie. Juste un exemple. 

0
Lesly Revenge

Les relations 1: 1 n'ont pas vraiment de sens si vous êtes en normalisation, car tout ce qui serait 1: 1 serait conservé dans le même tableau.

Dans le monde réel, cependant, c'est souvent différent. Vous voudrez peut-être séparer vos données pour qu'elles correspondent à l'interface de vos applications.

0
Eppz

Vous pouvez créer une table de relations un à un s'il existe un avantage de performance significatif. Vous pouvez mettre les champs rarement utilisés dans une table séparée.

0
kta

Peut-être si vous avez une sorte d'objets typés dans votre base de données.

Dites dans un tableau, T1, vous avez les colonnes C1, C2, C3… avec une relation un à un. C'est bon, c'est sous forme normalisée. Supposons maintenant que dans une table T2, vous avez les colonnes C1, C2, C3,… (les noms peuvent différer, mais disons que les types et le rôle sont les mêmes) avec également une relation un à un. C'est bon pour T2 pour les mêmes raisons que pour T1.

Cependant, dans ce cas, je suis d’accord pour une table séparée T3, contenant C1, C2, C3… et une relation un à un de T1 à T3 et de T2 à T3. Je vois encore mieux si il existe une autre table, avec laquelle il existe déjà un un à plusieurs C1, C2, C3… disons de la table A à plusieurs lignes de la table B. Ensuite, au lieu de T3, vous utilisez B, et vous avez une relation un à un de T1 à B, la même chose de T2 à B, et toujours la même relation multiple de A à B.

Je pense que la normalisation ne correspond pas à cela et que cela peut être une idée extérieure: identifier des types d’objet et déplacer des objets du même type vers leur propre pool de stockage, en utilisant une relation un à un de certaines tables et un à plusieurs relation de quelques autres tables.

0
Hibou57