Il y a plusieurs raisons pour lesquelles utiliser une seule "grande table de dieu" est mauvais. Je vais essayer d'illustrer les problèmes avec une base de données exemple constituée. Supposons que vous essayez de modéliser des événements sportifs. Nous dirons que vous voulez modéliser les jeux et les équipes jouant dans ces jeux. Cela pourrait ressembler à une conception avec plusieurs tables (ceci est très simpliste, donc ne vous laissez pas prendre aux endroits où une normalisation supplémentaire pourrait être appliquée):
Teams
Id | Name | HomeCity
Games
Id | StartsAt | HomeTeamId | AwayTeamId | Location
et une seule base de données de table ressemblerait à ceci
TeamsAndGames
Id | TeamName | TeamHomeCity | GameStartsAt | GameHomeTeamId | GameAwayTeamId | Location
Commençons par créer des index sur ces tables. Si j'avais besoin d'un index sur la ville natale pour une équipe, je pourrais facilement l' ajouter à la Teams
table ou à la TeamsAndGames
table. N'oubliez pas que chaque fois que vous créez un index, celui-ci doit être stocké sur un disque et mis à jour à mesure que des lignes sont ajoutées à la table. Dans le cas de la Teams
table, c'est assez simple. Je mets dans une nouvelle équipe, la base de données met à jour l'index. Mais qu'en est-il pour TeamsAndGames
? Eh bien, la même chose s'applique à partir duTeams
exemple. J'ajoute une équipe, l'index est mis à jour. Mais cela arrive aussi quand j'ajoute un jeu! Même si ce champ sera nul pour un jeu, l’index doit quand même être mis à jour et stocké sur disque pour ce jeu. Pour un index, cela ne semble pas trop grave. Mais lorsque vous avez besoin de nombreux index pour les multiples entités entassées dans cette table, vous perdez beaucoup d’espace à les stocker et beaucoup de temps de traitement à les mettre à jour pour les éléments où ils ne s’appliquent pas.
Deuxièmement, la cohérence des données. Dans le cas de l'utilisation de deux tables distinctes, je peux utiliser des clés étrangères de Games
table en Teams
table pour définir les équipes qui jouent dans une partie. Et en supposant que les colonnes HomeTeamId
et AwayTeamId
ne soient pas annulées, la base de données garantira que chaque jeu que je mets a 2 équipes et que ces équipes existent dans ma base de données. Mais qu'en est-il du scénario à table unique? Eh bien, comme il y a plusieurs entités dans cette table, ces colonnes devraient pouvoir être annulées (vous pouvez les rendre non annulables et y insérer des données parasites, mais ce n'est qu'une idée horrible). Si ces colonnes ont la valeur NULL, la base de données ne peut plus garantir que, lorsque vous insérez un jeu, elle comporte deux équipes.
Mais que faire si vous décidez d'y aller quand même? Vous configurez les clés étrangères de sorte que ces champs renvoient vers une autre entité de la même table. Mais maintenant, la base de données s'assurera simplement que ces entités existent dans la table, et non qu'elles sont du type correct. Vous pouvez très facilement définir GameHomeTeamId
l'ID d'un autre jeu et la base de données ne se plaindra pas du tout. Si vous avez essayé cela dans le scénario à plusieurs tables, la base de données s’y adapterait.
Vous pouvez essayer d'atténuer ces problèmes en disant "bon, nous nous assurerons simplement de ne jamais le faire dans le code". Si vous avez confiance en votre capacité à écrire du code sans bug la première fois et en votre capacité à prendre en compte toutes les combinaisons étranges d'essais qu'un utilisateur peut essayer, continuez. Personnellement, je ne suis pas confiant dans ma capacité à faire l'une ou l'autre de ces choses, je vais donc laisser la base de données me donner un filet de sécurité supplémentaire.
(Cela empire encore si votre conception consiste à copier toutes les données pertinentes entre les lignes au lieu d'utiliser des clés étrangères. Toute incohérence orthographique / autre donnée sera difficile à résoudre. Comment savoir si "Jon" est une faute de frappe de "John "ou si c'était intentionnel (parce que ce sont deux personnes distinctes)?)
Troisièmement, presque chaque colonne doit pouvoir être nullable ou doit être remplie avec des données copiées ou des données vides. Un jeu n'a pas besoin d'un TeamName
ou TeamHomeCity
. Donc soit chaque jeu a besoin d’une sorte d’espace réservé, soit il doit pouvoir être annulé. Et s’il est annulable, la base de données acceptera avec plaisir une partie sans TeamName
. Il faudra également une équipe sans nom, même si votre logique d’affaires indique que cela ne devrait jamais se produire.
Il existe une poignée d'autres raisons pour lesquelles vous souhaitez utiliser des tables séparées (notamment pour préserver la santé mentale des développeurs). Il y a même plusieurs raisons pour lesquelles une table plus grande peut être meilleure (la dénormalisation améliore parfois les performances). Ces scénarios sont rares (et généralement mieux gérés lorsque vous disposez de mesures de performance indiquant que le problème est réellement, pas un index manquant ou autre chose).
Enfin, développez quelque chose qui sera facile à maintenir. Ce n'est pas parce que ça marche que ça va. Essayer de maintenir des tables divines (comme des classes divines) est un cauchemar. Vous vous arrêtez juste pour la douleur plus tard.