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 !

35voto

JacquesB Points 19878

Je serais d'accord pour avoir une table unique pour toutes les références, mais des tables supplémentaires comme BookReferences et ainsi de suite pour les métadonnées qui ne sont pas applicables à tous les types de références.

La recherche et l'interrogation ne seraient pas plus difficiles - après tout, vous pourriez simplement créer une vue qui regroupe toutes les informations comme dans la solution à table unique, puis interroger cette vue de manière plus approfondie.

Tout regrouper dans un seul tableau avec de nombreuses valeurs nulles peut sembler être la solution la plus simple, mais en réalité, cela entraîne de nombreux problèmes. Par exemple : Avec des tables séparées, vous pouvez définir quels champs sont requis pour chaque BookReference, mais si tout est dans une seule table, chaque champ doit être nullable et donc optionnel. Il serait aussi plus facile d'insérer des données invalides, comme une référence de livre qui contient aussi par erreur un nom de journal non nul.

Edit : Certaines personnes semblent craindre les jointures. Ne craignez pas la jointure ! Si vous utilisez exactement la même jointure dans plusieurs requêtes, ce serait en effet fastidieux, mais dans ce cas, la jointure devrait être définie dans un fichier de type voir et vos requêtes doivent interroger cette vue. Les vues sont vraiment l'abstraction de base des bases de données relationnelles, et vous devriez les utiliser pour les mêmes raisons que vous utilisez les fonctions dans le code : pour éviter les répétitions, et pour encapsuler et créer des abstractions.

Edit : Il y a quelques commentaires concernant les performances. Il est très difficile de deviner à l'avance les performances des schémas de BD, car elles sont souvent non intuitives. Par exemple, une jointure entre plusieurs tables peut facilement être plus rapide qu'un balayage complet d'une seule table - tout dépend du type de requête, de la nature des données, des index disponibles et ainsi de suite. En outre, dans de nombreux systèmes de bases de données, vous pouvez utiliser des fonctionnalités telles que les vues matérialisées pour optimiser les performances de différentes requêtes sans compromettre le modèle logique. La "dénormalisation pour la performance" est surtout un culte de la marchandise de nos jours, à moins que vous ne soyez Google ou Flickr.

10voto

onedaywhen Points 24594

"la vie est plus facile avec une seule grande table" : J'ai vu la conséquence naturelle de cela, à savoir un tableau de plus de 100 colonnes, et je peux vous dire que ce n'est pas un plaisir de travailler avec. Le principal problème est que les concepteurs de ces tables ont tendance à omettre les contraintes nécessaires pour garantir l'intégrité des données :

CHECK (NOT (type <> 'book' AND field_common_to_book_and_journal IS NOT NULL))

et ainsi de suite.

J'espère qu'après avoir écrit plusieurs centaines de contraintes de ce type, le concepteur aura peut-être des doutes sur toutes ces colonnes annulables :)

7voto

Je vous conseille de commencer par concevoir correctement la base de données, c'est-à-dire d'utiliser la normalisation pour vous assurer que les tables ne contiennent que des données relatives à une seule chose (livre, journal, etc.) et que les attributs sont stockés dans la bonne table.

Si, à l'avenir, cela crée des problèmes de performance, vous pouvez le dé-normaliser en moins de tables, mais il est peu probable que cela soit un problème, sauf si vous avez une énorme base de données.

Créez une table qui contiendra les attributs communs à toutes les références.

Créez des tables distinctes pour contenir les attributs spécifiques à chaque type de référence.

L'autre question est de savoir si vous aurez de nombreuses références à un seul travail, par exemple des centaines de références à une revue particulière. La normalisation suggère alors d'avoir une table qui contient les revues (titre, auteur, revue), une table qui contient les informations de référence spécifiques aux revues (article, page), et une autre table qui contient les données communes à toutes les références (date de référence, type de référence).

4voto

Marcin Gil Points 16951

Le fait d'avoir une seule table avec le champ "type" posera des problèmes lors de l'ajout d'un nouveau type de référence qui nécessite des champs supplémentaires. L'extension des valeurs du champ "type" ne pose pas de problème, mais vous devrez ajouter des colonnes à la table, remplir les valeurs par défaut pour toutes les lignes actuelles, etc.

Avec des tables séparées, il serait très facile d'ajouter un nouveau type de référence (et de générer automatiquement un formulaire pour celui-ci !) et la recherche ne serait pas plus difficile.

3voto

Corey Trager Points 11334

Je pense qu'il faut prévoir à quoi ressemblera le SQL pour chacune des solutions. Si vous faites cet exercice, vous constaterez que le fait de tout mettre dans une seule table est le plus facile à coder et conduira probablement à la meilleure performance. Il est plus facile de séparer les éléments que vous voulez dans une table que de les rassembler dans plusieurs tables.

Disons que ma table unique ressemble à ceci :

1 id
2 types
3 champ-commun-à-livre-et-journal
4 champ spécifique au livre
5 spécifique au domaine-à-journal

Si je ne m'intéresse qu'aux livres, je peux créer une vue, ou simplement un sql, comme ceci :

create view book as  
select id, field_common-to-book-and-journal, field-specific-to-book
from my-one-big-table
where type = 'book'

Ainsi, il est facile de simuler que les données se trouvent dans des tableaux séparés lorsque je le souhaite.

Mais, si je commence par mettre les données dans des tables séparées, je finirai par écrire du SQL comme ceci :

select id, field-common-to-book-and-journal from books
union
select id, field-common-to-book-and-journal from journal-articles
union
.... etc, for each type

Je ne sais pas ce qu'il en est des autres bases de données, mais faire des unions dans SQL Server peut être coûteux et il y a des restrictions lorsqu'on travaille avec des types de données comme ntext.

Si vous suivez les conseils d'Olavk, votre SQL pour combiner les types dans une seule requête ressemblera à ceci :

select 
    common.id, 
    common.field-common-to-book-and-journal, 
    book.field-specific-to-book 
    journal.field-specific-to-journal
from common-table common
left outer join book-specific-table book on 
left outer join journal-specific-table journal on
... etc, for each type

J'ai travaillé avec des systèmes qui utilisaient ces trois méthodes et de loin, la vie est plus facile avec une seule grande table.

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