Question

Mon employeur, une petite entreprise de fournitures de bureau, est de changer de fournisseur et je regarde à travers leur contenu électronique pour arriver à un schéma de base de données robuste; notre schéma précédent a été à peu près juste jeté ensemble, sans aucune pensée du tout, et il est à peu près conduit à un modèle de données insupportable avec des informations corrompues, incohérentes.

Les données du nouveau fournisseur est beaucoup mieux que l'ancien de, mais leurs données est ce que je qualifierais hypernormalized . Par exemple, la structure de leur catégorie de produits a 5 niveaux: CAPITAINE, Département, classe, sous-classe, bloc produit. En outre, le contenu du bloc de produit a la longue description, les termes de recherche et les noms d'image pour les produits (l'idée est qu'un bloc de produit contient un produit et toutes les variantes - par exemple un stylo particulier pourrait venir à l'encre noire, bleue ou rouge, tous ces les articles sont essentiellement la même chose, de sorte qu'ils appliquent à un seul bloc de produit). Dans les données que j'ai donné, cela est exprimé sous la forme de la table des produits (je dis « table », mais c'est un fichier plat avec les données) ayant une référence à l'identifiant unique du bloc de produit.

Je suis en train de trouver un schéma robuste pour accueillir les données que je suis fourni avec, car je vais devoir le charger assez rapidement, et les données qu'ils me ont donné ne semble pas correspondre au type des données qu'ils fournissent pour la démonstration sur leur site web de l'échantillon ( http://www.iteminfo.com ). En tout état de cause, je ne cherche pas à réutiliser leur structure de présentation il est donc un point discutable, mais je naviguer sur le site pour obtenir quelques idées sur la façon de structurer les choses.

Ce que je ne suis pas sûr de si oui ou non je conserver les données dans ce format, ou par exemple regrouper Maître / Département / Classe / Sous-classe en une seule table « Catégories », en utilisant une relation auto-référencement et lien qui à un bloc de produit (bloc de produit doit être conservé séparément car il n'est pas une « catégorie » en tant que telle, mais un groupe de produits pour une catégorie donnée). À l'heure actuelle, la table des blocs de produits de référence à la table sous-classe, donc cela changerait à « category_id » si je les regrouper ensemble.

Je suis probablement vais à créer une vitrine de commerce électronique faisant usage de ces données avec Ruby on Rails (ou que mon plan, en tout cas), donc je suis en train d'éviter de s'accrocher plus tard ou d'avoir une application pléthorique - peut-être je lui donner trop d'idée mais je préfère être sûr que désolé; nos données précédentes était un vrai gâchis et a coûté des dizaines de milliers de compagnie de dollars en ventes perdues en raison de données incohérentes et inexactes. Aussi je vais rompre avec les conventions Rails un peu en faisant en sorte que ma base de données est robuste et applique des contraintes (je prévois de le faire au niveau de l'application, aussi), de sorte que quelque chose que je dois considérer ainsi.

Comment voulez-vous aborder une telle situation? Gardez à l'esprit que j'ai les données à charger déjà dans des fichiers plats qui simulent une structure de table (j'ai dit de documentation qui sont des colonnes qui et quelles références sont mis en place); Je suis en train de décider si je devais les garder comme normalisés tels qu'ils sont actuellement, ou si je dois chercher à consolider; Je dois être conscient de la façon dont chaque méthode aura une incidence sur la façon dont je programme le site en utilisant Rails car si je n'entérinent, il y aura essentiellement 4 « niveaux » de catégories dans une seule table, mais cela semble certainement plus facile à gérer que des tables séparées pour chaque niveau, car, en dehors de la sous-catégorie (qui relie directement aux blocs de produits), ils ne le font pas faire tout sauf montrer le niveau suivant de la catégorie en dessous. Je suis toujours une perte pour la « meilleure » façon de gérer les données comme ça -. Je connais le dicton « Normaliser jusqu'à ce qu'il fait mal, dénormaliser puis jusqu'à ce qu'il fonctionne » mais je ne l'ai jamais vraiment eu à mettre en œuvre jusqu'à présent

Était-ce utile?

La solution

Je préférerais l'approche « hypernormalized » sur un modèle de données dénormalisé. Le tableau de référencement auto vous avez mentionné pourrait réduire le nombre de tables vers le bas et simplifier la vie d'une certaine manière, mais en général ce type de relation peut être difficile à traiter. requêtes hiérarchiques deviennent une douleur, tout comme la cartographie d'un modèle d'objet à ce (si vous décidez d'aller dans cette voie).

Un couple de supplémentaire ne va pas se joint à faire du mal et gardera l'application plus maintenable. À moins les performances se dégradent en raison du nombre excessif de jointures, je choisirais de laisser les choses comme elles sont. En prime si l'un de ces niveaux de tables nécessaires fonctionnalités supplémentaires ajoutés, vous ne serez pas rencontrer des problèmes parce que vous les fusionnées tous dans la table de référence de soi.

Autres conseils

Je suis totalement en désaccord avec les critiques sur les structures de table auto-référencement pour les hiérarchies parent-enfant. La structure de liste chaînée fait l'interface utilisateur et la programmation de la couche d'affaires plus facile et plus maintenable dans la plupart des cas, étant donné que les listes chaînées et les arbres sont la voie naturelle pour représenter ces données dans les langues que les couches de l'interface utilisateur et d'affaires seraient généralement mises en œuvre.

Les critiques au sujet de la difficulté de maintenir les contraintes d'intégrité des données sur ces structures est parfaitement valable, bien que la solution simple est d'utiliser une table de fermeture qui héberge le plus difficile de vérifier les contraintes. Le tableau de fermeture est facile à entretenir avec des déclencheurs.

Le compromis est un peu de complexité supplémentaire dans la base de données (table de fermeture et déclencheurs) pour beaucoup moins de complexité dans le code de l'interface utilisateur et de la couche d'affaires.

Si je comprends bien, vous voulez prendre leurs tables séparées et les transformer en une hiérarchie qui est conservée dans une table unique avec une FK auto-référencement.

Il est généralement une approche plus souple (par exemple, si vous souhaitez ajouter un cinquième niveau), mais SQL et des modèles de données relationnelles tendance à ne pas fonctionner correctement avec les listes chaînées comme celui-ci, même avec une nouvelle syntaxe comme MS SQL Serveurs. CTEs Il est vrai que, CTEs faire beaucoup mieux que.

Il peut être difficile et coûteux de faire respecter les choses, comme un produit doit toujours être au quatrième niveau de la hiérarchie, etc.

Si vous décidez de le faire de cette façon, vérifiez définitivement Joe Celko SQL de Smarties , qui je crois a une section ou deux sur la modélisation et de travailler avec des hiérarchies dans SQL ou mieux encore obtenir son livre qui est consacré au sujet ( noreferrer arbres Joe Čelko et dans SQL pour hiérarchies Smarties ).

Normalization implique l'intégrité des données, qui est la suivante:. Chaque forme normale réduit le nombre de situations où vous données sont incohérentes

En règle générale, a un objectif denormalization de plus rapide querying, mais conduit à un espace accru, l'augmentation du temps DML, et, last but not least, des efforts accrus pour rendre les données cohérentes.

On écrit généralement un code plus rapide (écrit plus vite, pas le code plus rapide) et le code est moins sujette à des erreurs si les données sont normalized.

tables faisant référence auto presque toujours se révéler bien pire pour interroger et de moins bons résultats que les tables normalisées. Ne pas le faire. Il peut sembler à vous d'être plus élégant, mais il est pas et est une technique de conception de base de données très pauvres. Personnellement, la structure que vous avez décrit semble très bien pour ne pas me hypernormalized. Une base de données correctement normalisée (avec les clés étrangères, ainsi que les valeurs par défaut, les déclencheurs (le cas échéant des règles complexes) et les contraintes de validation des données) est également beaucoup plus susceptibles d'avoir des données précises et cohérentes. Je suis d'accord d'avoir la base de données respecter les règles, probablement cela fait partie des raisons pour lesquelles la dernière application avait de mauvaises données, car les règles ne sont pas appliquées au bon endroit et les gens ont pu se déplacer dans les facilement. Non pas que l'application ne doit pas vérifier aussi bien (pas de point même d'envoyer une date non valide, par exemple, pour le datbase à l'échec à l'insertion). Depuis la refonte youa, je mettrais plus de temps et d'efforts dans la conception des contraintes nécessaires et le choix des types de données correctes (ne pas stocker les dates que les données de chaîne par exemple), que d'essayer de rendre la structure normalisée parfaitement ordinaire look plus élégant.

Je porterais en aussi près de leur modèle possible (et si possible, je recevrais les fichiers qui correspondent à leur schéma - pas une version aplatie). Si vous apportez les données directement dans votre modèle, ce qui se passe si les données qu'ils envoient commence à briser les hypothèses dans la transformation au modèle de votre application interne?

Il vaut mieux apporter leurs données, exécuter des contrôles de santé mentale et vérifier que les hypothèses ne sont pas violés. Ensuite, si vous avez un modèle spécifique à l'application, la transformer en ce que pour une utilisation optimale de votre application.

Ne pas dénormaliser. Essayer de acheive une bonne conception de schéma par dénormalisation est comme essayer de se rendre à San Francisco en conduisant loin de New York. Il ne vous dit pas dans quelle direction aller.

Dans votre situation, vous voulez savoir quel schéma normalisé voudrait. Vous pouvez baser que en grande partie sur le schéma source, mais vous devez savoir ce que les dépendances fonctionnelles (FD) dans les données. Ni le schéma source ni les fichiers aplaties sont garantis pour vous révéler tous les IFD.

Une fois que vous savez ce qu'est un schéma normalisé ressemblerait, vous devez maintenant comprendre comment concevoir un schéma qui répond à vos besoins. Ce schéma est que un peu moins complètement normalisée, alors que ce soit. Mais préparez-vous des difficultés dans la programmation de la transformation entre les données dans les fichiers aplatis et les données dans votre schéma Desgined.

Vous avez dit que les schémas précédents de votre entreprise coûtent des millions en raison de l'incohérence et l'inexactitude. Plus votre schéma normalisé est, plus vous êtes protégé d'incohérence interne. Cela vous laisse libre d'être plus vigilant sur l'inexactitude. Des données cohérentes qui est toujours mal peut être aussi trompeuse que les données incohérentes.

est votre devanture de magasin (ou quoi que ce soit vous construisez, pas tout à fait clair sur ce point) va toujours utiliser des données de ce fournisseur? pourriez-vous jamais changer de fournisseur ou ajouter des fournisseurs différents supplémentaires?

le cas échéant, la conception d'un schéma général qui répond vos besoins et cartographier les données du fournisseur à lui. Personnellement, je préfère souffrir le (très mineur) « douleur » d'une table de catégorie auto-référencement (hiérarchique) que de maintenir quatre (apparemment semi-inutile) niveaux de variantes de catégorie, puis l'année prochaine se rendent compte qu'ils ont ajouté un 5, ou introduit une gamme de produits avec seulement trois ...

Pour moi, la vraie question est: ce qui convient le mieux modèle

Il est comme comparer un tuple et une liste.

  1. Tuples sont d'une taille fixe et sont hétérogènes -. Ils sont "hypernormalized"
  2. Les listes sont une taille arbitrarty et sont homogènes.

J'utilise un Tuple quand je besoin d'un Tuple et une liste quand je besoin d'une liste; ils fondamentalement fins de serveur.

Dans ce cas, puisque la structure du produit est déjà bien défini (et je suppose pas susceptible de changer) alors je tenir à la « approche Tuple ». La puissance / utilisation réelle d'une liste (ou un motif de table récursive) est quand vous en avez besoin Détailler à une profondeur arbitraire, par exemple pour une nomenclature ou un arbre généalogique.

J'utiliser les deux approches dans certaines de ma base de données en fonction de la nécessité. Cependant, il y a aussi le « coût caché » d'un motif récurrent qui est que tous les ORM (pas sûr AR) soutenir le bien. De nombreux blocs de données modernes bénéficient d'un soutien pour « join-through » (Oracle), ID hiérarchie (SQL Server) ou d'autres motifs récurrents. Une autre approche consiste à utiliser une hiérarchie basée ensemble (qui repose généralement sur les déclencheurs / maintenance). Dans tous les cas, si le ORM utilisé ne prend pas en charge les requêtes récursives bien, il peut y avoir le supplément « coût » de l'utilisation de la DB au caractéristiques directement - soit en termes de génération ou de gestion des demandes manuelle / vue tels que les déclencheurs. Si vous n'utilisez pas un ORM génial, ou tout simplement utiliser un séparateur logique tel que iBatis, ce problème peut même pas appliquer.

En ce qui concerne la performance, le nouveau Oracle ou SQL Server (et probablement d'autres) SGBDR, il devrait être très comparable si ce serait le moindre de mes soucis: mais il faut vérifier les solutions disponibles à vos préoccupations SGBDR et de portabilité.

Tout le monde qui vous recommande de ne pas avoir une hiérarchie introduite dans la base de données, considérant que la possibilité d'avoir une table auto-référencé. Ce n'est pas la seule façon de modéliser la hiérarchie dans la base de données. Vous pouvez utiliser une approche différente, qui vous fournit l'interrogation plus facile et rapide sans utiliser des requêtes récursives. Disons que vous avez un grand ensemble de noeuds (catégories) dans la hiérarchie:

  

Set1 = (Noeud1 Node2 Node3 ...)

Tout nœud dans cet ensemble peut également être un autre en lui-même, qui contient d'autres noeuds ou ensembles imbriqués:

  

Nœud1 = (Nœud2 Node3 = (noeud 4 Node5 = (Node6) Node7))

Maintenant, comment nous pouvons modèle? Ayons chaque nœud d'avoir deux attributs, qui définissent les limites des nœuds qu'il contient:

  

Noeud = {Id: int, Min: int, Max: int}

Pour modéliser notre hiérarchie, nous venons attribuons les valeurs min / max en conséquence:

  

Noeud1 = {Id = 1, Min = 1, Max = 10}
  Node2 = {Id = 2, Min = 2, Max = 2}
  Node3 = {Id = 3, Min = 3, Max = 9}
  Node4 = {Id = 4, Min = 4, Max = 4}
  Node5 = {Id = 5, Min = 5, Max = 7}
  Node6 = {Id = 6, Min = 6, Max = 6}
  Node7 = {Id = 7, Min = 8, Max = 8}

Maintenant, pour interroger tous les nœuds sous le Set / Node5:

  

select n. * À partir de nœuds comme n, comme les nœuds de
  où s.Id = 5 et s.Min

La seule opération consommateur de ressources serait si vous souhaitez insérer un nouveau noeud, ou déplacer un nœud dans la hiérarchie, autant de dossiers seront affectés, mais cela est très bien, car la hiérarchie elle-même ne change pas très souvent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top