2010-04-26 3 views
4

Je conçois une base de données de produits où les produits peuvent avoir des attributs très différents selon leur type, mais les attributs sont fixes pour chaque type et les types ne sont pas gérables du tout. Par exemple:Conception de base de données: objets avec différents attributs

magazine: titre, ISSUE_NUMBER, pages, copies, close_date, RELEASE_DATE
WEB_SITE: nom, bande passante, frappe, date_from, date_to

Je veux utiliser InnoDB et faire respecter l'intégrité de la base de données autant que le permet le moteur. Quelle est la méthode recommandée pour gérer cela?

Je déteste ces dessins où les tables ont 100 colonnes et la plupart des valeurs sont NULL si je pensais à quelque chose comme ceci:

product_type 
============ 

product_type_id INT 
product_type_name VARCHAR 

product 
======= 

product_id INT 
product_name VARCHAR 
product_type_id INT -> Foreign key to product_type.product_type_id 
valid_since DATETIME 
valid_to DATETIME 

magazine 
======== 

magazine_id INT 
title VARCHAR 
product_id INT -> Foreign key to product.product_id 
issue_number INT 
pages INT 
copies INT 
close_date DATETIME 
release_date DATETIME 

web_site 
======== 

web_site_id INT 
name VARCHAR 
product_id INT -> Foreign key to product.product_id 
bandwidth INT 
hits INT 
date_from DATETIME 
date_to DATETIME 

Ce peut gérer la suppression des produits mais ... en cascade, je suis pas convaincu ...

Répondre

5

Il s'agit d'une conception OO classique pour les tables relationnelles incompatibilité d'impédance. La conception de table que vous avez décrite est connue sous le nom de «table par sous-classe».Les trois modèles les plus communs sont tous compromis par rapport à ce que vos objets ressemblent vraiment dans votre application:

  1. table par classe béton
  2. Tableau par hiérarchie
  3. Tableau par la sous-classe

La conception vous n'aimez pas - "où les tables ont 100 colonnes et la plupart des valeurs sont NULL" - 2. est une table pour stocker toute la hiérarchie de spécialisation. C'est le moins flexible pour toutes sortes de raisons, y compris - si votre application nécessite une nouvelle sous-classe, vous devez ajouter des colonnes. Le design que vous décrivez s'adapte beaucoup mieux car vous pouvez l'ajouter en ajoutant un nouveau tableau de sous-classes décrit par une valeur dans product_type.

L'option restante - 1. Table par classe concrète - n'est généralement pas souhaitable en raison de la duplication impliquée dans l'implémentation de tous les champs communs dans chaque table de spécialisation. Bien que, les avantages sont que vous n'aurez pas besoin d'effectuer des jointures et les tables de sous-classe peuvent même être sur différentes instances db dans un très grand système.

Le design que vous avez décrit est parfaitement viable. La variation ci-dessous est ce que cela pourrait donner si vous utilisiez un outil ORM pour effectuer vos opérations CRUD. Remarquez comment l'ID de chaque table de sous-classe est la valeur FK de la table parente dans la hiérarchie. Un bon ORM gérera automatiquement la table CRUD de sous-classe correcte en fonction de la valeur des valeurs du discriminateur dans product.id et product.product_type_id seul. Que vous envisagiez ou non d'utiliser un ORM, consultez la documentation de sous-classe jointe d'hibernate, ne serait-ce que pour voir les décisions de conception prises.

product 
======= 

id INT 
product_name VARCHAR 
product_type_id INT -> Foreign key to product_type.product_type_id 
valid_since DATETIME 
valid_to DATETIME 

magazine 
======== 

id INT -> Foreign key to product.product_id 
title VARCHAR 
.. 

web_site 
======== 

id INT -> Foreign key to product.product_id INT 
name VARCHAR 
.. 
+0

Belle vue d'ensemble de trois conceptions possibles, merci. Toutes les réponses étaient excellentes mais je ne peux en choisir qu'une: <:-) ' –

2

vous semblez être à peu près sur la bonne voie, sauf que vous devrez peut-être tenir compte de la différence entre un « produit » et ce que l'on appelle souvent « une unité de maintien de stock » (SKU). Une boîte de 25 unités de trombones (d'un certain type spécifique) est-elle le même "produit" qu'une boîte de 50 unités? En termes de magasin ou de système d'inventaire, la distinction compte; dans certains cas, en effet, une simple distinction dans emballage de ce qui est par ailleurs la même quantité du même "produit" sous-jacent peut vous donner des SKU distincts à suivre. Vous devez décider où vous voulez garder la trace de ce problème, si cela a de l'importance pour votre application (il peut être OK pour que les produits soient présentés comme vous le faites, et traiter de l'emballage pour les SKU dans d'autres tables, par exemple, même si pour certaines applications, cela pourrait être un léger surcoût).

1

Ceci est en fait un moyen standard pour "appliquer" une sorte de conception OO dans un SGBDR classique. Tous les attributs "communs" vont sur la table principale (par exemple, le prix, s'il est maintenu au niveau de la table des produits, pourrait facilement faire partie de la table principale) tandis que les détails vont sur une sous-table. En théorie, si vous avez des sous-sous-types (par exemple, les magazines peuvent être sous-typés dans les journaux quotidiens et les périodiques quadrichromiques, peut-être avec des périodiques ayant un intervalle de dates), vous pouvez ajouter un ou plusieurs sous-niveaux. ...

Ceci est une conception assez courante (et éprouvée). La seule préoccupation est que la table principale sera toujours jointe avec au moins une sous-table pour la plupart des opérations. Si vous avez des zillions d'éléments, cela pourrait avoir des conséquences sur les performances. D'autre part, une opération courante comme la suppression d'un élément (je suggérerais une suppression logique, mettre un drapeau à "vrai" sur la table principale) serait faite une fois pour chaque type de sous-type.

De toute façon, allez-y. Et peut-être google autour de "Object orienté vers les mappages de SGBDR" ou quelque chose pour a complete discussion.

Questions connexes