Supertype / sous-type déterminant entre les catégories: chevauchement disjoint complet ou incomplet

11

Je crée une base de données d'inventaire qui stocke du matériel informatique, comme des ordinateurs de bureau, des ordinateurs portables, des commutateurs, des routeurs, des téléphones mobiles, etc. J'utilise un modèle de supertype / sous-type, où tous les appareils sont stockés dans une seule table et des informations spécifiques est placé dans des tables de sous-types. Mon dilemme est de choisir entre les deux modèles suivants:

entrez la description de l'image ici

Dans le diagramme du haut, tous les appareils partagent des sous-types communs. Par exemple, les ordinateurs de bureau et les ordinateurs portables auraient des enregistrements dans les tableaux suivants: Device, NetworkDevice. Un commutateur aurait des enregistrements dans: Device, NetworkDevice. Un routeur aurait des enregistrements dans: Device, NetworkDevice, WANDevice. Tout appareil dont nous suivons l'emplacement aura un enregistrement dans Emplacement. Quelques avantages et inconvénients auxquels j'ai pensé pour cette configuration:

  • Pro: la sélection d'enregistrements sur la base d'un champ commun, comme Hostname ou LocationID, est plus facile.
  • Pro: pas de champs nuls.
  • Inconvénients: les tables qui devraient être incluses dans les opérations CRUD pour un périphérique particulier ne sont pas évidentes et peuvent confondre les futurs DBA.

Dans le diagramme du bas, tous les appareils ont leur propre sous-type (il y a plus de classes d'appareils qui ne sont pas affichées ici). Dans cette situation, il est évident dans quels enregistrements de tables être insérés ou sélectionnés. Les ordinateurs de bureau et les ordinateurs portables vont dans Ordinateur, etc. Quelques avantages et inconvénients auxquels j'ai pensé pour cette configuration:

  • Pro: Il est immédiatement évident quelles tables utiliser pour les opérations CRUD pour les sous-types.
  • Pro: Il suffit d'utiliser une seule table pour les opérations CRUD.
  • Contre: la sélection d'enregistrements sur la base de champs de sous-type communs nécessite que toutes les tables soient combinées, par exemple la recherche par nom d'hôte ou LocationID.

Dans les deux cas, le champ ClassDiscriminator est placé dans des tables de sous-types à utiliser avec une contrainte CHECK pour contrôler les types qui peuvent être insérés.

Y a-t-il des recommandations pour lesquelles la conception est meilleure, ou est-ce complètement une question d'opinion et dépend de l'objectif prévu de la base de données?

EDIT: Une question spécifique que j'ai à propos du chevauchement de la table "NetworkDevice". Ce tableau est destiné à contenir les informations réseau de tout périphérique avec un nom d'hôte et / ou une adresse IP, qu'il s'agisse d'un ordinateur, d'un commutateur ou d'un routeur. Le chevauchement de ce tableau peut-il causer des problèmes, ou est-il correct de le mettre en œuvre de cette façon?

Merci d'avance pour toute contribution fournie. Veuillez demander si des informations supplémentaires sont nécessaires.

TheSecretSquad
la source
Voir dba.stackexchange.com/questions/15199/… pour une question similaire à laquelle il a été répondu
Stephen Senkomago Musoke

Réponses:

15

L'implémentation physique du sous-typage dans une base de données est un problème complexe. Sauf si vous avez une situation où il offre des avantages convaincants (voir ci-dessous pour un ou deux exemples), il ajoute de la complexité à la mise en œuvre tout en offrant relativement peu de valeur.

Après avoir fait cela avec un sous-typage vraiment complexe (applicaitons et peines sur un système de gestion des affaires judiciaires, structures de contrats d'assurance commerciale à risques combinés disparates), je suppose que j'ai quelques observations à ce sujet. Certains cas d'angle importants sont:

  • Si le nombre total de champs de base de données dans les sous-types est relativement faible (disons: moins de 100) ou s'il existe des points communs importants entre les sous-types, la division des sous-types en tables physiques distinctes est probablement de peu de valeur. Cela ajoutera des frais généraux importants aux rapports de requêtes et de recherches. Dans la plupart des cas, il est préférable d'avoir une seule table et de gérer votre sous-typage dans l'application. (Probablement le plus proche de votre problème)

  • Si votre sous-typage est très disjoint et que différents sous-types ont des structures de données dépendantes du type qui les suspendent (c'est-à-dire des tables enfants ou des structures plus complexes), alors les tables de sous-types ont du sens. Dans ce cas, chaque sous-type a probablement relativement peu de points communs dans l'application (c'est-à-dire qu'il y a probablement un sous-système entier dans l'application dédié à ce sous-type). La plupart des rapports et des requêtes se produiront probablement au sein d'un sous-type donné, les requêtes de type croisé étant principalement limitées à une poignée de champs communs. (Système de gestion des affaires judiciaires)

  • Si vous avez un grand nombre de sous-types avec des attributs disparates et / ou une exigence pour le rendre configurable, une structure générique et des métadonnées supplémentaires peuvent être plus appropriées. Voir cet affichage SO pour un aperçu de certaines approches possibles. (Système d'administration des polices d'assurance)

  • Si vous avez un très grand nombre de champs avec peu de points communs entre vos sous-types et peu d'exigences pour interroger les tables de sous-types (c.-à-d. Rien de très important dans la manière des jointures externes multidirectionnelles contre vos tables de sous-types), alors sous- les tables de types peuvent aider à gérer l'étalement des colonnes. (Version pathologiquement complexe de votre problème)

  • Certains mappeurs O / R ne prennent en charge qu'une approche particulière de la gestion des sous-classes.

Dans la plupart des cas, les tables de sous-types physiques dans un schéma de base de données sont un peu une solution à la recherche d'un problème, car elles ont potentiellement des effets secondaires indésirables.

Dans votre cas, je suppose que vous avez un nombre relativement modeste de sous-types et un nombre gérable d'attributs. Votre diagramme et votre question n'indiquent aucune intention de suspendre les tables enfants des enregistrements. Je suggère que vous envisagiez d'utiliser la première option suggérée ci-dessus et de maintenir une table et de gérer le sous-typage dans votre application.

ConcernedOfTunbridgeWells
la source
Merci pour votre réponse détaillée. Au départ, je voulais tout garder dans une table, mais certains champs pour les appareils ne s'appliquent pas aux autres et je me retrouverais avec un tas de champs nuls. Par exemple, tous les enregistrements d'inventaire auraient des champs pour le type de circuit et le fournisseur de services qui sont spécifiques aux routeurs. Tous les enregistrements auraient également un champ de numéro de téléphone qui n'a de sens que si l'appareil est un téléphone. Avez-vous des suggestions sur la façon de gérer cela?
TheSecretSquad
2
@reallythecrash - La surcharge pour les champs nullables est d'environ un octet par champ, donc en termes d'utilisation des ressources, c'est beaucoup moins de surcharge que de se joindre à des tables de sous-classe. Vraiment le seul inconvénient est que la table sera un peu désordonnée avec beaucoup de nulls.
ConcernedOfTunbridgeWells
3
@reallythecrash - Si vous le voulez vraiment (et votre SGBD le prend en charge - vous n'avez pas spécifié ce que vous utilisez), vous pouvez configurer des contraintes de vérification en fonction du discriminateur de type qui applique null / non-null sur les champs appropriés à la classe.
ConcernedOfTunbridgeWells
3

Envisagez d'abord de développer un modèle de données logique solide en utilisant les règles de hiérarchie de classification de la modélisation des données trouvées dans Enterprise Model Patterns , un livre de David Hay. Lors de la création d'une hiérarchie de classification, chaque occurrence (ligne) doit être d'un et d'un seul sous-type. Cela signifie que les sous-types s'excluent mutuellement. La classification doit être basée sur une caractéristique unique, fondamentale et immuable. L'utilisation de cette règle de base apportera beaucoup de clarté à votre modèle. Dans le modèle que vous avez, la seule caractéristique à classer est le but de l'appareil - un téléphone, un commutateur réseau, un ordinateur, un routeur, etc. Chaque appareil doit être d'un et d'un seul de ces types. Ainsi, par exemple, l'emplacement ne serait pas un sous-type. Les attributs tels que l'adresse IP appartiennent au super type.

Je pense que vous constaterez que le nombre de types d'appareils sera suffisamment grand pour justifier un modèle EAV comme mentionné dans une autre réponse. Le livre de David Hay que je référence couvre ce modèle très efficacement. Cependant, si le nombre de sous-types est peu élevé, vous pouvez en règle générale décider de n'implémenter qu'une table de super-type avec de nombreuses colonnes annulables, uniquement des tables de sous-types avec des colonnes dupliquées, ou les deux. Si chaque sous-type varie considérablement dans ses attributs et n'a pas de relations au niveau du super-type, vous pouvez utiliser uniquement des tables de sous-types. Si le contraire est vrai, vous pouvez utiliser uniquement des tables de super-type. S'il y a un mélange, alors implémentez les deux.

Notez enfin que vous pouvez toujours implémenter un modèle EAV en tant que schéma de table de base, puis créer une couche d'abstraction de vue qui présente les données à l'application sous forme de tables de super et sous-types. Cela vous donne de la flexibilité au niveau de la couche de stockage mais de la compréhension au niveau de la couche de vue d'application.

Todd Everett
la source
Merci pour l'info Todd. L'une des questions que je me pose concerne le tableau "Périphérique réseau". Cette table est destinée à contenir des enregistrements pour tout périphérique possédant un nom d'hôte et une adresse IP. Cela signifie que les commutateurs, les ordinateurs et les routeurs auraient tous leurs données liées au réseau stockées dans cette table. D'après ce que j'ai lu, cela s'appelle un sous-type se chevauchant où la table des sous-types contient des données associées pour plus d'un type. Savez-vous si c'est quelque chose qui devrait être évité, ou si je suis d'accord pour l'implémenter de cette façon?
TheSecretSquad
Todd, concernant votre déclaration "créez une couche d'abstraction de vue qui présente les données à l'application ...". Cela ressemble à une excellente idée. J'ai pensé à utiliser les vues exactement comme vous l'avez décrit, mais j'avais quelques questions à ce sujet. Je sais qu'il est acceptable d'utiliser des vues pour interroger et afficher les données dans mon application, mais est-il courant d'utiliser des vues pour les insertions et les mises à jour? Je sais qu'il existe certaines restrictions sur la façon dont vos requêtes doivent être structurées (pas de clause order by, etc.) pour insérer / mettre à jour à l'aide d'une vue. Si la requête est structurée correctement, est-il conseillé d'utiliser la vue pour les insertions et les mises à jour?
TheSecretSquad
D'après mon expérience, les sous-types qui se chevauchent confondent les choses à un niveau logique, c'est pourquoi je recommandais de commencer par développer un modèle logique complet. Vous pouvez utiliser le LDM pour clarifier la portée et la compréhension avant de traiter le stockage. Dans le modèle actuel présenté, il y a une certaine confusion dans la compréhension entre la nature fondamentale d'une chose - un appareil - et l'endroit où cet appareil vit dans l'espace. Clarifiez cela dans le LDM. Évitez également le sous-type qui se chevauche dans la base de données physique, sauf si vous l'utilisez pour partitionner verticalement des colonnes, auquel cas il ne tape pas du tout.
Todd Everett
En ce qui concerne la couche d'abstraction, vous pouvez utiliser un déclencheur "au lieu de" pour rendre une vue pouvant être mise à jour. Les restrictions que vous mentionnez (sans ordre) sont des restrictions dans la vue SQL elle-même et non dans son utilisation. Pour l'insertion / la mise à jour, il n'y a pas de commande de toute façon. Vous avez également la possibilité d'écrire un module pour gérer les détails de l'insertion / mise à jour ou d'écrire une procédure stockée pour la gérer. Je ne vois aucun problème à utiliser l'une de ces méthodes car les performances sont acceptables. Pour les écritures de type singleton, cela devrait aller. Les mises à jour en masse peuvent être un problème.
Todd Everett
2

Un produit n'est pas un inventaire. L'inventaire et les produits sont distincts.

Un produit est vraiment une spécification d'un produit, pas une chose physique.

La chose physique est un actif que l'entreprise possède (ou stocke). Vous pouvez avoir des actifs que vous suivez par numéro de série (actifs discrets) ou des actifs que vous suivez uniquement par quantité (actifs en stock).

Je voudrais regarder le livre de ressources du modèle de données de Silverston Vol 1. Il a un bon schéma pour proudcts, fonctionnalités, prix, inventaire. Cela vous fera gagner beaucoup de temps.

Neil McGuigan
la source
1
+1 point pour avoir mentionné le livre de ressources du modèle de données de Silverston. J'ai jeté un coup d'œil et c'était instructif. Au plaisir de lire plus en détail, comme je pense que toute personne ayant des questions sur la modélisation des données devrait le faire. Merci.
TheSecretSquad
0

L'une des questions que je poserais est la suivante: pourquoi suivez-vous les différents attributs de vos articles en stock? - Ou, plus précisément, que faites-vous avec ces informations d'attribut?

Si vous avez beaucoup de rapports ou de formulaires qui donnent un sens spécifique à des attributs particuliers, vous devez utiliser l'approche recommandée par ConcernedOfTunbridgeWell. Si, d'autre part, ces attributs sont enregistrés dans le but de les répertorier, ou éventuellement de les comparer avec des attributs similaires d'appareils similaires, alors vous pouvez en fait avoir une (rare) bonne excuse pour utiliser EAV. Je sais que "l'EAV est du mal pur" pour de nombreuses raisons, sauf dans de très rares cas où ces raisons n'ont pas d'importance pour une application spécifique. La vôtre pourrait être une telle application.

Jetez un œil à cette réponse concernant la conception d'un système d'inventaire d'appareils et cette réponse concernant la conception d'un système de catalogue de produits pour voir comment une approche EAV pourrait simplifier votre application avec une discussion sur quels sont exactement les risques de l'EAV et comment juger si ces risques peuvent ne pas s'appliquer à votre application spécifique.

Joel Brown
la source
Merci pour votre participation. J'ai envisagé l'EAV, mais j'ai pensé que je pourrais obtenir un modèle assez bon sans avoir à recourir aux complexités liées à l'EAV.
TheSecretSquad