Pourquoi le modèle relationnel pour une base de données est-il important?

61

J'aborde un projet pour lequel je vais devoir mettre en place une base de données avec mon patron; nous sommes une toute petite start-up, l'environnement de travail est donc profondément personnel.

Il m'avait déjà fourni une des bases de données de l'entreprise et cela allait complètement à l'encontre de ce que l'on m'avait appris (et que je lisais) à l'école pour le SGBDR. Par exemple, il y a des bases de données entières ici composées d'une table (par base de données indépendante). Une de ces tables a plus de 20 colonnes et pour le contexte, voici quelques noms de colonnes d' une table:

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

Le fait est que là où il devrait avoir des tables individuelles contenant les données de l'entité (nom, taille, date d'achat, etc.), il les place dans une grande table par base de données.

Je souhaite améliorer cette conception, mais je ne suis pas certain de savoir pourquoi un modèle de données correctement normalisé et segmenté améliorerait réellement ce produit. Bien que je connaisse la conception de bases de données de collège et que je comprenne comment le faire, je ne sais pas pourquoi cela améliore réellement les bases de données.

Pourquoi un bon schéma relationnel améliore-t-il une base de données?

8protons
la source
33
Un mot: normalisation.
Robert Harvey
9
Électeur proche - justifiez-vous! :-)
Robbie Dee
6
Il est courant que les nouveaux employés critiquent les procédures établies sans comprendre les raisons qui les sous-tendent, même si ces raisons ne sont pas techniquement valables. Commencez par comprendre pourquoi votre patron l’a construit de cette façon. Il / elle peut très bien savoir que ce n'est pas un bon design, mais ne pas avoir les connaissances (ou plus probablement le temps) pour le faire mieux. Toute modification que vous proposez sera probablement mieux accueillie si vous reconnaissez respectueusement les raisons de la conception actuelle.
Pedro
5
He [the boss] had given me one of his databases before and it completely went against what I was taught (and read about) in school for RDBMS<- Bienvenue dans le monde réel!
Möoz
5
Je me souviens de ma citation préférée dans la base de données relationnelle: "Normaliser jusqu'à ce que ça fasse mal, dénormaliser jusqu'à ce que ça marche"
Jake

Réponses:

70

L'argument de performance est généralement celui qui est le plus intuitif. Vous voulez surtout souligner la difficulté d'ajouter de bons index dans une base de données mal normalisée (remarque: il existe des cas extrêmes où la dénormalisation peut en fait améliorer les performances, mais lorsque vous êtes tous les deux inexpérimentés avec des bases de données relationnelles, vous ne risquez probablement pas facilement voir ces cas).

Un autre argument est l'argument de la taille de stockage. Une table dénormalisée avec beaucoup de redondances nécessitera beaucoup plus de stockage. Cela joue également sur l'aspect performance: plus vous avez de données, plus vos requêtes seront lentes.

Il existe également un argument un peu plus difficile à comprendre, mais qui est en réalité plus important, car vous ne pouvez pas le résoudre en utilisant davantage de matériel. C'est le problème de cohérence des données. Une base de données correctement normalisée veillera à ce qu'un produit portant un identifiant spécifique porte toujours le même nom. Mais dans une base de données dénormalisée, de telles incohérences sont possibles. Il faut donc prendre des précautions particulières pour éviter les incohérences, ce qui prendra du temps à la programmation pour bien fonctionner et causera toujours des bogues qui vous coûteront cher pour la satisfaction du client.

Philipp
la source
19
La mise en entrepôt de données est un cas majeur de dénormalisation , en particulier si vous avez la garantie de ne jamais modifier une grande quantité de données et que vous souhaitez l'interroger plus rapidement et plus efficacement aux dépens de l'espace de stockage. Bonne réponse, il s’agit là d’un simple rappel pour les débutants en SQL qui ne savent pas pourquoi une solution autre que 3NF serait souhaitable.
11
Je ne suis pas sûr de savoir pourquoi l'argument de cohérence est "plus difficile à comprendre". Cela me semble beaucoup plus simple: si une valeur change, toutes les copies de cette valeur doivent être mises à jour. La mise à jour d'une seule copie est beaucoup moins sujette aux erreurs que la mise à jour de centaines ou de milliers de copies des mêmes données. Ceci s’applique également aux relations entre les données. (Si la relation est stockée de deux manières, je dois mettre à jour les deux copies de la relation.) Il s'agit d'un problème extrêmement courant dans les bases de données dénormalisées. il est très difficile d'empêcher cette corruption dans la pratique (une exception est l'utilisation de type de vue matérialisée).
jpmc26
4
Ce dernier paragraphe devrait être mis en gras. :-) Sans normalisation, il est impossible de garantir l'intégrité des données. Le contrôle des entrées uniquement au niveau de la couche Business Logic est une tâche insensée, car chaque base de données non normalisée présente finalement une sorte d'anomalie de données.
DanK
2
@IsmaelMiguel Selon la pratique habituelle, les données de base telles que celles-ci ne sont jamais effacées de la base de données. Vous ne pouvez que supprimer le logiciel en définissant un indicateur indiquant qu'il n'est plus disponible. Dans ce cas particulier, il serait judicieux d’avoir une relation de clé étrangère entre les produits et les commandes, ce qui signifie que la base de données générera une erreur lorsque vous essayez de supprimer un produit référencé par des commandes.
Philipp
24

Je vais devoir mettre en place une base de données avec mon patron ...

L'utilisation d'un logiciel de gestion de base de données dédié pourrait être considérablement plus simple (désolé, je n'ai pas pu résister).

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

Si cette base de données ne se préoccupe que « l' exploitation forestière » qui produit a été vendu où, quand et par qui, alors vous pourrait être en mesure d'étendre la définition de « base de données OK » assez loin pour le couvrir. Si ces données sont utilisées pour autre chose, alors elles sont vraiment très pauvres.

Mais ...

Est-ce que l'application / les requêtes utilisant ces données répondent mal / lentement? Si non, alors il n'y a pas de vrai problème à résoudre. Bien sûr, cela a l'air moche, mais si ça marche, vous n'obtiendrez pas de "points" pour suggérer que "pourrait" être mieux.

Si vous pouvez trouver des symptômes définis (c.-à-d. Des problèmes) qui semblent provenir d'une mauvaise modélisation des données, protégez une meilleure solution. Prenez une copie de l'une de ces "bases de données", normalisez les données et voyez si votre solution fonctionne mieux. Si c'est nettement mieux (et je m'attendrais à ce que toute opération de mise à jour de ces données soit considérablement améliorée), adressez-vous à votre patron et montrez-lui l'amélioration.

Il est parfaitement possible de recréer sa "vue à table unique" des données avec .. bien .. Vues.

Phill W.
la source
11
La résistance à la table unique weltanschauung provient souvent de personnes inexpérimentées avec SQL qui ne comprennent pas les jointures - en particulier en ce qui concerne les données manquantes, à savoir les jointures externes.
Robbie Dee
6
@RobbieDee Plus généralement, cela provient de personnes qui ont vu des données dénormalisées se corrompre en devenant incohérentes. Je suis une telle personne. Phill ne suggère ce type de structure que dans la situation suivante: il s'agit d'une sorte de tableau de journalisation / rapport dans lequel les données ne seront jamais mises à jour ou ne seront mises à jour que si elles sont nettoyées et complètement dérivées d'autres sources.
jpmc26
2
Même si l'application fonctionne de manière acceptable avec une base de données comme celle-ci, elle n'est toujours pas flexible, contrairement à une base de données correctement normalisée. Si le nom du magasin ou de la société change, il devra être mis à jour partout, plutôt que dans une table de magasin ou de société. Dans certains cas, c'est peut-être ce que vous voulez (par exemple, si les données sont principalement collectées à des fins d'archivage), mais nous devons en savoir plus sur l'application spécifique.
Zach Lipton
1
@Zach: d'accord, c'est pourquoi le journal des ventes est potentiellement un cas acceptable pour cela. Supposons que vous souhaitiez associer chaque vente à la dénomination du magasin au moment de la vente, et non au "nom actuel du magasin". Toute tentative de "normalisation" introduirait une complexité considérable (parce que le tableau il faudrait une série dans le temps, pas une valeur par magasin)
Steve Jessop
Peut-être une règle de base serait-elle que si la seule complexité introduite par une normalisation proposée est que quelques requêtes ont maintenant besoin d'être jointes pour collecter toutes les colonnes dont elles ont besoin pour être rapportées, vous devez alors exécuter pas à pied pour apporter cette modification: - )
Steve Jessop
14

Pourquoi un bon schéma relationnel améliore-t-il une base de données?

La réponse est: cela n'améliore pas toujours une base de données. Vous devez savoir que ce que vous avez probablement appris s'appelle la troisième forme normale .

D'autres formes sont valables dans certaines situations, ce qui est essentiel pour répondre à votre question. Votre exemple ressemble à First Normal Form , si cela vous aide à vous sentir mieux dans son état actuel.

Les règles 3NF établissent des relations entre les données qui "améliorent" une base de données:

  1. Empêcher les données non valides d'entrer dans votre système (si une relation est de 1 à 1, une erreur est générée malgré le code écrit dessus). Si vos données sont cohérentes dans la base de données, cela risque moins d'entraîner des incohérences en dehors de votre base de données.

  2. Il fournit un moyen de valider le code (par exemple, une relation plusieurs-à-un est un signal pour restreindre les propriétés / comportements d'un objet). Lors de l'écriture de code pour utiliser la base de données, les programmeurs remarquent parfois que la structure de données est un indicateur du fonctionnement de leur code. Ils peuvent également fournir des informations utiles si la base de données ne correspond pas à leur code. (Cela ressemble plus à un voeu pieux, malheureusement.)

  3. Définissez des règles qui peuvent vous aider de manière significative à réduire les erreurs lors de la création d'une base de données, de sorte que vous ne la construisez pas en fonction d'exigences arbitraires pouvant survenir à tout moment de la vie d'une base de données. Au lieu de cela, vous évaluez systématiquement les informations pour atteindre des objectifs spécifiques.

  4. Les structures de base de données appropriées améliorent les performances en connectant les données de manière à minimiser le stockage de données, à minimiser les appels de stockage à extraire les données, à maximiser les ressources en mémoire et / ou à minimiser le tri / la manipulation de données pour votre ensemble de données particulier, par rapport à la requête que vous êtes. exécuter contre elle. Mais la structure "appropriée" dépend de la quantité de données, de la nature des données, du type de requête, des ressources système, etc. En normalisant, vous risquez d’aggraver les performances (par exemple, si vous chargez toutes les données sous la forme d’une table). une requête). Le traitement des transactions (OLTP) et la veille stratégique (entrepôt de données) sont très différents.

Dans une petite entreprise avec de petits ensembles de données, vous constaterez peut-être qu'il n'y a rien de mal avec la façon dont il est maintenant. Sauf que si vous grandissez, il sera difficile de "réparer" plus tard, car à mesure que la table grossit, les systèmes qui l'utilisent vont probablement ralentir.

Habituellement, vous voudrez mettre l'accent sur les transactions rapides au fur et à mesure que l'entreprise grandit. Toutefois, si vous consacrez plus de temps à ce projet au lieu d’autres éléments dont la société pourrait avoir besoin plus rapidement, vous ne rencontrerez peut-être jamais ce problème car votre société ne se développe jamais vraiment. C'est le "défi de pré-optimisation" - où passer votre temps précieux en ce moment.

Bonne chance!

Jim
la source
4
Sans mentionner, mais je pense qu'un point important pour les programmeurs est que l'édition d'une "chose" nécessite l'édition d'une seule ligne plutôt que d'avoir à boucler toute la base de données pour trouver et remplacer cette seule chose.
Slebetman
@slebetman Vous ne devriez jamais avoir de boucle côté code pour mettre à jour plusieurs lignes dans une seule table, qu'elle soit normalisée ou non. Utilisez une WHEREclause. Bien sûr, cela peut toujours mal se passer, mais cela est moins probable dans une situation normalisée puisqu'il suffit de faire correspondre une ligne via la clé primaire.
JPMc26
@ jpmc26: En bouclant la base de données, je veux dire construire une requête pour mettre à jour toutes les lignes affectées. Parfois, un seul WHERE suffit. Mais j'ai vu des structures impies qui nécessitent des sous-sélections dans la même table pour obtenir toutes les lignes affectées sans affecter les lignes qui ne devraient pas changer. J'ai même vu des structures où une seule requête ne peut pas faire le travail (l'entité qui nécessite des modifications réside dans différentes colonnes en fonction de la ligne)
slebetman
Beaucoup d'excellentes réponses à cette question, et ce ne fut pas une exception.
Mike Chamberlain
11

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 Teamstable ou à la TeamsAndGamestable. 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 Teamstable, 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 duTeamsexemple. 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 Gamestable en Teamstable pour définir les équipes qui jouent dans une partie. Et en supposant que les colonnes HomeTeamIdet AwayTeamIdne 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 GameHomeTeamIdl'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 TeamNameou 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.

Becuzz
la source
1
"Équipes: Id | Nom | HomeCity". Assurez-vous simplement que votre schéma de données ne permet pas à votre application de déclarer à tort que le Super Bowl XXXIV a été remporté par les Rams de Los Angeles. Considérant que SB XXXIV devrait figurer dans une requête pour tous les championnats remportés par l'équipe connue sous le nom de LA Rams. Il y a des "tables divines" meilleures et pires, et vous en avez certainement présenté une mauvaise. Un meilleur serait "ID de jeu | nom de l'équipe locale | ville de l'équipe locale | nom de l'équipe à l'extérieur | ville de l'équipe | le jeu commence à | etc ...". Ce qui s’agit d’une première tentative de modélisation d’informations du type "New Orleans Saints @ Chicago Bears 1p Eastern".
Steve Jessop
6

Citation du jour: " Théorie et pratique devraient être les mêmes ... en théorie "

Tableau dénormalisé

Votre table hold-it-all, unique en son genre, contient des données redondantes et présente un avantage: elle permet de créer des rapports sur ses lignes très simples à coder et à exécuter rapidement, car aucune jointure n'est nécessaire. Mais ceci à un coût élevé:

  • Il contient des copies redondantes de relations (par exemple, IngCompanyIDet vrCompanyName). La mise à jour des données de base peut nécessiter de mettre à jour beaucoup plus de lignes que dans un schéma normalisé.
  • Ça mélange tout. Vous ne pouvez pas garantir un contrôle d'accès facile au niveau de la base de données, par exemple en veillant à ce que l'utilisateur A ne puisse mettre à jour que les informations de la société et que l'utilisateur B ne contienne que des informations sur le produit.
  • Vous ne pouvez pas garantir de règles de cohérence au niveau de la base de données (par exemple, une clé primaire pour faire en sorte qu'il n'y ait qu'un seul nom de société pour un identifiant de société).
  • Vous ne tirez pas pleinement parti de l'optimiseur de base de données, qui pourrait identifier les stratégies d'accès optimales pour une requête complexe, en tirant parti de la taille des tables normalisées et des statistiques de plusieurs index. Cela pourrait rapidement compenser l'avantage limité d'éviter les jointures.

Table normalisée

Les inconvénients ci-dessus sont des avantages pour le schéma normalisé. Bien sûr, les requêtes pourraient être un peu plus complexes à écrire.

En bref, le schéma normalisé exprime beaucoup mieux la structure et les relations entre vos données. Je serai provocateur et dirai que c'est le même genre de différence qu'entre la discipline requise pour utiliser un ensemble de tiroirs de bureau ordonnés et la facilité d'utilisation d'une corbeille à papier.

Christophe
la source
5

Je pense que votre question comporte au moins deux parties:

1. Pourquoi des entités de types différents ne devraient-elles pas être stockées dans la même table?

Les réponses les plus importantes ici sont la lisibilité et la rapidité du code. A SELECT name FROM companies WHERE id = ?est simplement beaucoup plus lisible qu’un SELECT companyName FROM masterTable WHERE companyId = ?et vous êtes moins susceptible d’interroger par inadvertance un non-sens (par exemple, SELECT companyName FROM masterTable WHERE employeeId = ?cela ne serait pas possible lorsque les entreprises et les employés sont stockés dans des tables différentes). En ce qui concerne la rapidité, les données d'une table de base de données sont extraites en lisant la table complète de manière séquentielle ou en lisant un index. Les deux sont plus rapides si la table / index contient moins de données, et c'est le cas si les données sont stockées dans des tables différentes (et vous ne devez lire que l'une des tables / index).

2. Pourquoi les entités d'un même type devraient-elles être divisées en sous-entités stockées dans différentes tables?

Ici, la raison principale est d'éviter les incohérences dans les données. Avec l'approche à table unique, pour un système de gestion des commandes, vous pouvez stocker le nom du client, l'adresse du client et l'ID de produit du produit que le client a commandé en tant qu'entité unique. Si un client commandait plusieurs produits, vous auriez plusieurs instances du nom et de l'adresse du client dans votre base de données. Dans le meilleur des cas, votre base de données contient des données en double, ce qui peut la ralentir un peu. Mais le pire cas est que quelqu'un (ou un code) a commis une erreur lors de la saisie des données, de sorte qu'une entreprise se retrouve avec des adresses différentes dans votre base de données. Cela seul est déjà assez grave. Mais si vous deviez interroger l'adresse d'une entreprise en fonction de son nom (par exemple,SELECT companyAddress FROM orders WHERE companyName = ? LIMIT 1) vous obtiendrez de manière arbitraire une des deux adresses et ne vous rendriez même pas compte d’une incohérence. Toutefois, chaque fois que vous exécutez la requête, vous pouvez obtenir une adresse différente, en fonction de la résolution interne de votre requête par le SGBD. Cela cassera probablement votre demande ailleurs et la cause première de cette casse sera très difficile à trouver.

Avec l’approche multi-tables, vous vous rendrez compte qu’il existe une dépendance fonctionnelle du nom de la société à l’adresse de la société (si une société ne peut avoir qu’une seule adresse), vous stockez le tuple (companyName, companyAddress) dans une seule table (par exemple: company), et le tuple (productId, companyName) dans une autre table (par exemple order). Une UNIQUEcontrainte sur la companytable peut alors imposer que chaque société ne possède qu'une seule adresse dans votre base de données, de sorte qu'aucune incohérence pour les adresses de société ne puisse jamais se produire.

Remarque: dans la pratique, pour des raisons de performances, vous devez probablement générer un identifiant unique (companyId) unique pour chaque entreprise et l'utiliser comme clé étrangère au lieu d'utiliser directement le nom de l'entreprise. Mais l'approche générale reste la même.

Rêveur
la source
3

TL; DR - Ils conçoivent la base de données en fonction de la façon dont ils ont été enseignés à l’école.

J'aurais pu écrire cette question il y a 10 ans. Il m'a fallu un certain temps pour comprendre pourquoi mes prédécesseurs ont conçu leurs bases de données comme ils l'ont fait. Vous travaillez avec quelqu'un qui soit:

  1. Acquis la plupart de leurs compétences en conception de bases de données en utilisant Excel comme base de données ou
  2. Ils utilisent les meilleures pratiques de leur sortie de l'école.

Je ne soupçonne pas que c'est le numéro 1 puisque vous avez réellement des numéros d'identification dans votre tableau, alors je suppose que le numéro 2.

Après ma sortie de l'école, je travaillais pour un magasin qui utilisait un AS / 400 (alias IBM i). J'ai trouvé certaines choses étranges dans la conception de leurs bases de données et j'ai commencé à demander que nous apportions des changements pour suivre la façon dont on m'a appris à concevoir des bases de données. (J'étais stupide à l'époque)

Il a fallu à un ancien programmeur patient pour m'expliquer pourquoi les choses se passaient ainsi. Ils n’avaient pas changé de schéma car cela aurait causé la défaillance de programmes plus anciens que moi. Littéralement, le code source d'un programme avait une date de création de l'année précédant ma naissance. Sur le système sur lequel nous travaillions, leurs programmes devaient implémenter toute la logique et les opérations gérées par le planificateur de requêtes de votre base de données. (Vous pouvez voir cela en exécutant EXPLAIN sur l'une de vos requêtes)

Il maîtrisait les techniques que j'essayais de mettre en œuvre, mais le fonctionnement du système était plus important que les modifications à apporter "parce que cela contrevenait à ce que l'on m'avait enseigné". Chaque nouveau projet que nous avons commencé a fait le meilleur usage du modèle relationnel que nous avons pu. Malheureusement, d’autres programmeurs / consultants de cette époque ont toujours conçu leurs bases de données comme s’ils utilisaient les anciennes contraintes de ce système.


Quelques exemples de ce que j'ai rencontré qui ne correspondaient pas au modèle relationnel:

  • Les dates étaient stockées sous forme de nombre de jours du calendrier Julien nécessitant une jointure à un tableau de dates pour obtenir la date réelle.
  • Tables dénormalisées avec des colonnes séquentielles du même type (par exemple code1,code2, ..., code20)
  • Colonnes CHAR de longueur NxM représentant un tableau de N chaînes de longueur M.

Les raisons qui m'ont été données pour ces décisions de conception étaient toutes basées sur les contraintes du système lors de la conception initiale de la base de données.

Dates - On m'a dit qu'il fallait plus de temps de traitement pour utiliser les fonctions de date (quel mois, jour ou jour de semaine) pour traiter une date que pour créer un tableau de chaque date possible avec toutes ces informations.

Colonnes séquentielles du même type - L'environnement de programmation dans lequel elles se trouvaient ont permis à un programme de créer une variable de tableau sur une partie de la ligne. Et c'était un moyen plus facile de réduire le nombre d'opérations de lecture.

Colonnes CHAR NxM Longueur - Il était plus facile de déplacer les valeurs de configuration dans une colonne pour réduire les opérations de lecture de fichier.

Un exemple mal conçu en équivalent C reflétant l'environnement de programmation qu'ils avaient:

#define COURSE_LENGTH 4
#define NUM_COURSES 4
#define PERIOD_LENGTH 2

struct mytable {
    int id;
    char periodNames[NUM_COURSES * PERIOD_LENGTH];  // NxM CHAR Column
    char course1[COURSE_LENGTH];
    char course2[COURSE_LENGTH];
    char course3[COURSE_LENGTH];
    char course4[COURSE_LENGTH];
};

...

// Example row
struct mytable row = {.id= 1, .periodNames="HRP1P2P8", .course1="MATH", .course2="ENGL", .course3 = "SCI ", .course4 = "READ"};

char *courses; // Pointer used to access the sequential columns
courses = (char *)&row.course1;


for(int i = 0; i < NUM_COURSES; i++) {

    printf("%d: %.*s -> %.*s\n",i+1, PERIOD_LENGTH, &row.periodNames[PERIOD_LENGTH * i], COURSE_LENGTH,&courses[COURSE_LENGTH*i]);
}

Les sorties

1: HR -> MATH
2: P1 -> ENGL
3: P2 -> SCI
4: P8 -> LIRE

D'après ce qu'on m'a dit, certaines de ces pratiques étaient considérées comme une pratique exemplaire à l'époque.

Core.B
la source