31 votes

Une table ou plusieurs ?

J'essaie de concevoir une application pour contenir des informations sur les références académiques. Le problème est que chaque type de référence (articles de revues, livres, articles de journaux, etc.) nécessite des informations différentes. Par exemple, une référence à un journal nécessite à la fois un titre de journal et un titre d'article, ainsi qu'un numéro de page, tandis qu'un livre nécessite un éditeur et une date de publication, ce qui n'est pas le cas des articles de journaux.

Par conséquent, dois-je stocker toutes les références dans une seule table de ma base de données et laisser les champs vides lorsqu'ils ne s'appliquent pas, ou dois-je avoir plusieurs tables telles que BookReferences, JournalReferences, NewspaperReferences et placer les références appropriées dans chacune d'elles. Le problème serait alors que cela rendrait la recherche dans toutes les références plus difficile, et que l'édition devrait probablement être faite plus séparément.

(Je prévois d'utiliser Ruby on Rails pour ce projet, mais je doute que cela fasse une différence pour cette question de conception).

Mise à jour :

D'autres avis sur la question ? J'espérais obtenir une réponse simple disant qu'une méthode particulière était définitivement considérée comme "la meilleure" - mais comme d'habitude les choses ne sont pas aussi simples que cela. L'option Single-Table Inheritance semble assez intéressante, mais il n'y a pas beaucoup d'informations à son sujet que je puisse trouver très facilement - je vais peut-être poster une autre question sur ce site à ce sujet.

Je suis partagé entre Réponse d'Olvak y La réponse de Corey . La réponse de Corey donne une bonne raison pour laquelle celle d'Olvak n'est pas la meilleure, mais la réponse d'Olvak donne de bonnes raisons pour lesquelles celle de Corey n'est pas la meilleure ! Je n'avais jamais réalisé que cela pouvait être si difficile...

Tout autre conseil serait le bienvenu !

0voto

gnobal Points 7377

Vous demandez la normalisation de la base de données. Jeff Atwood en a parlé dans son article Peut-être que normaliser n'est pas normal . C'est une bonne lecture.

0voto

Keith Williams Points 437

Ce que j'ai fini par faire dans le passé, c'est d'utiliser des sous-catégories : avoir une seule table avec tous les éléments de la base de données. commun puis plusieurs tables qui peuvent avoir une relation zéro ou un avec la table "principale".

L'exemple ci-dessous est similaire à ce que nous utilisons "dans la nature" ; il construit essentiellement une structure de données hiérarchique, où chaque nœud peut être un dossier ou un document :

CREATE TABLE Node (
  Id int identity primary key,
  ParentId int null references Node.ParentId,
  Name varchar(50) not null,
  Description varchar(max) null
)

CREATE TABLE Doc (
  Id int primary key references Node.Id,
  FileExtension char(3) not null,
  MimeType varchar(50) not null,
  ContentLength bigint not null,
  FilePathOnDisk varchar(255)
)

CREATE TABLE Folder (
  Id int primary key references Node.Id,
  ReadOnly bit not null
)

Donc votre GetFolder sproc fera l'affaire :

SELECT n.Id, n.ParentId, n.Name, n.Description, f.ReadOnly
FROM Node n 
JOIN Folder f ON n.Id = f.Id
WHERE f.Id = @Id

Cela se traduit très bien par un héritage basé sur les classes :

public class Folder : Node
{
  public bool IsReadOnly { get; set; }
  ...etc
}

0voto

Olavk présente de bons arguments, et Corey donne une excellente explication détaillée. La lecture des informations de Corey, cependant, me donne une conclusion de la réponse d'Olavk. Gardez à l'esprit qu'en fonction de ce que vous faites avec l'information, vous pouvez finir par faire deux étapes dans votre recherche. Trouvez l'élément, puis pour chaque référence, faites une sélection directe sur ce qui vous intéresse.

Considérez également l'idée de tout stocker dans plusieurs tables et de les lire à partir d'une seule table. C'est ce que je fais pour une grande base de données dont la plupart des requêtes ont besoin de certaines informations communes, mais la disposition complète en tables multiples est toujours nécessaire. Les insertions sont un peu ralenties par les déclencheurs qu'elles déclenchent (dans mon cas, un par fichier, chaque fichier étant responsable d'un million de lignes insérées), mais mes requêtes de sélection ultérieures peuvent passer de quelques minutes à quelques secondes.

Entreposage de données :)

0voto

Dragoljub Points 145

J'ai eu une discussion sur ces questions il y a quelque temps avec mon supérieur. Bien sûr, je ne pouvais pas prouver que " multi-tableau hiérarchique approche" (voir La réponse de olavk ) est meilleur, mais je l'ai senti ! Je choisirais toujours cette méthode. Une table racine avec tous les champs que les entités ont en commun, et 1-1 tables enfant avec les champs qu'elles n'ont pas en commun. Si nécessaire, cette approche peut être étendue à d'autres tables enfant, pour autant que la logique métier et les autres entités en retirent quelque chose. En d'autres termes, je ne pense pas qu'il soit nécessaire d'aller trop loin dans ce domaine.

Je suis également contre la création des tables "enfants" séparées sans la table Root, où chaque table a une copie des mêmes champs. Je pense La réponse de Corey suggère une telle approche comme exemple d'un mauvais modèle multi-table, et il la critique également. Je voudrais ajouter que le fait de devoir écrire des jointures n'est pas le principal problème de cette approche. Ce n'est pas un problème du tout, puisque la plupart des requêtes de base de données ont de nombreuses jointures, et c'est une chose normale. Il est difficile de créer des relations avec d'autres tables - vous avez toujours besoin d'un Id et d'un TypeId pour savoir quelle table est liée à celle-ci. Dans le cas d'une table Root, vous n'avez besoin que de l'Id.

-1voto

Galghamon Points 1421

Pourquoi pas les deux ? Ayez votre gâteau et mangez-le aussi !

Il existe une autre option quelque part entre la "grande table" et la BD "entièrement normalisée" qui combine vraiment le meilleur des deux mondes : vous pouvez utiliser quelque chose appelé vues matérialisées qui sont comme des vues en ce sens qu'ils sont tout aussi flexibles et que vous interrogez autant de tables que nécessaire, en configurant toutes les jointures, etc., mais ils sont aussi comme des tables en ce sens que les résultats sont réellement stockés dans une table.

L'avantage de ce système est qu'une fois que vous l'avez mis en place et que vous avez décidé quand il doit être rafraîchi (chaque fois que l'une des tables sous-jacentes change, ou peut-être juste une fois par nuit), vous n'avez plus à vous en soucier. Vous pouvez interroger la vue matérialisée comme s'il s'agissait d'une grande table (car c'est le cas), et les performances seront rapides (plus rapides qu'en utilisant l'instruction select qui se trouve derrière). Plus important encore, vous n'avez pas à vous soucier de l'intégrité des données. C'est le rôle de la base de données.

Si vous ne disposez pas d'une base de données qui prend en charge cette fonctionnalité, vous pouvez tout de même utiliser cette idée en construisant un tableau à partir des résultats de la vue sous forme de travail par lots chaque nuit.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X