Conception de la base de données: nouvelle table par rapport aux nouvelles colonnes

38

(Il a été suggéré que cela soit rediffusé ici à partir de StackOverflow)

Vous avez actuellement une table .. et vous devez commencer à y ajouter de nouvelles colonnes de données. Tous les enregistrements (même les nouvelles données après l'ajout des nouvelles colonnes de données) n'auront pas de données. Je me demande donc si cela convient mieux à une nouvelle table, car il s’agit en réalité d’une extension de certaines lignes de données et ne s'applique donc pas à toutes les lignes.

En d'autres termes, étant donné qu'il y aura beaucoup de colonnes inutilisées pour ces nouveaux éléments de données, il semble que cela conviendrait mieux à un nouveau tableau?

Le premier tableau est un enregistrement des pages vues (actuellement 2 millions d’enregistrements)

- id
- Adresse IP
- fois visionné
- created_at timestamp
- rendez-vous amoureux

pour chaque adresse IP, un enregistrement est créé chaque jour - et des pages vues consécutives sont ajoutées aux heures vues par jour.

des champs supplémentaires seraient pour le suivi du point d'origine (par exemple, source / support / campagne Google Analytics)

Toutes les visites n'auront pas cette information. Je suppose que 10% environ des lignes auront les données (car elles ne sont généralement attribuées que lors de la première visite).

L’utilisation principale des données serait d’attribuer l’origine des personnes. Cela peut finir par être utilisé plus fréquemment (ce qui semble alors se prêter à la seule table)

Appréciez les commentaires - pouvez ajouter plus si nécessaire

cgmckeever
la source

Réponses:

29

Vous vous débattez avec le partitionnement vertical. Il s'agit d'une technique de conception de base de données physique destinée à améliorer les performances. Comme pour toute technique de conception de base de données physique, son applicabilité dépend des requêtes spécifiques que vous tentez d'optimiser et du potentiel de cette technique pour les optimiser. D'un point de vue logique, si ces nouveaux champs dépendent de la clé candidate de votre entité, ce sont des faits la concernant qui lui appartiennent. Tout d’abord, vous devez vous assurer de bien comprendre la dépendance fonctionnelle de ces nouveaux champs sur les clés de votre candidat afin de vous assurer qu’il s’agit bien de faits sur les pages vues quotidiennement. Si tel est le cas, décider de les partitionner dans une autre table constitue une optimisation des performances qui ne doit être effectuée que si elle atteint vos objectifs de performance.

En général, le partitionnement vertical est utile si vous souhaitez interroger ces nouvelles colonnes de manière peu fréquente et distincte des autres colonnes de la table d'origine. En plaçant ces colonnes dans une autre table partageant le même PK que votre table existante, vous pouvez l'interroger directement lorsque vous voulez ces nouvelles colonnes et obtenir un rendement beaucoup plus important, car vous disposerez de beaucoup plus de lignes par page sur le disque pour cette nouvelle table. comme toutes les colonnes de la table d'origine ne seront pas assis sur ces lignes. Cependant, si vous interrogez toujours ces colonnes avec les colonnes de la table d'origine, une partition verticale n'aurait pas beaucoup de sens car vous devrez toujours faire une jointure externe pour les obtenir. Les pages des tables sur disque entrent dans le pool de mémoire tampon d’un SGBD indépendamment, jamais pré-jointes, et donc cette jointure devra avoir lieu à chaque exécution de requête même si les données sont épinglées dans le pool de mémoire tampon. Dans ce scénario, les colonnes NULLABLE de la table d'origine permettraient au moteur de stockage de SGBD de les stocker efficacement lorsque NULL, ce qui éliminerait le besoin de rejoindre la récupération.

Il me semble que votre cas d'utilisation est le dernier et l'ajout de NULLABLE à votre table d'origine est la voie à suivre. Mais, comme pour tout ce qui concerne la conception des bases de données, cela dépend. Pour pouvoir prendre la bonne décision, vous devez connaître la charge de travail attendue et définir le choix. Un panneau de recherche de personnes constitue un bon exemple d'utilisation d'un partitionnement vertical. Votre application contient des informations très rarement renseignées sur une personne sur laquelle une personne peut souhaiter effectuer une recherche, mais le fait rarement. Si vous mettez ces informations dans une autre table, vous disposez de bonnes options en termes de performances. Vous pouvez écrire la recherche de manière à ce que vous ayez 2 requêtes - une qui utilise uniquement les informations principales, toujours renseignées (comme le nom de famille ou ssn), et un autre qui joint les informations très rarement renseignées uniquement lorsque la recherche est demandée. Vous pouvez également tirer parti de l'optimiseur de SGBD s'il est suffisamment intelligent pour reconnaître, pour un ensemble de variables hôte donné, que la jointure externe n'est pas nécessaire et ne l'exécutera pas. Vous ne devez donc créer qu'une requête.

Quelle plateforme de SGBD utilisez-vous? La manière dont la plate-forme gère le stockage des colonnes NULL, optimise votre requête ainsi que la disponibilité de la prise en charge des colonnes fragmentées (SQL Server l’a) a une incidence sur la décision. En fin de compte, je vous recommanderais d'essayer les deux conceptions dans un environnement de test avec des données et une charge de travail de la taille de la production, et de déterminer lequel correspond le mieux à vos objectifs de performance.

Todd Everett
la source
Ce que je veux dire par vous ne savez pas ce que vous entendez par "Cependant, si vous interrogez toujours ces colonnes avec les colonnes de la table d'origine, une partition verticale n'aurait pas beaucoup de sens car vous devrez toujours faire une jointure externe pour les obtenir." , vous n’auriez besoin de faire une jointure externe que si vous voulez les colonnes primaires, que les colonnes secondaires soient disponibles ou non, sinon vous utiliseriez un INNER JOIN, ce qui serait avantageux dans la plupart des cas (réduction du nombre de lignes examinées). ).
jmoreno
Merci pour toute l’aide apportée ici .. j’ai vraiment adoré l’ajout des champs, mais après y avoir bien réfléchi, j’ai compris que je devrais avoir quelques autres tableaux pour mieux tout identifier. Ce qui a finalement abouti est visiteur visiteur_visits (qui a un visiteur_id et contient la source) page_views (qui possède vistor_id et visiteur_visit_id) puisque je veux savoir exactement quelle page_view est attribuée à la visite, j'ai ajouté ce lien. J'ai un peu lutté avec elle, mais je pense que c'était la bonne décision
cgmckeever
10

Personnellement, je me penche vers l'ajout de colonnes à la table existante. La nouvelle table ne vous achète vraiment rien:

  • vous n'économisez pas vraiment beaucoup d'espace car les valeurs NULL de la table d'origine ne prennent pas d'espace, et la nouvelle table nécessite un identifiant qui compense toute économie de toute façon
  • vos questions deviennent plus complexes ... where newcolumn is not nulldevient unleft outer join

Dans un seul tableau, cela signifie simplement que la taille de vos lignes peut varier d'une page à l'autre - mais cela ne devrait pas affecter beaucoup de vos pages existantes, en particulier si votre index clusterisé se trouve sur une colonne à croissance monotone (identité ou date / heure).

Aaron Bertrand
la source
Étant donné que le tableau n'est actuellement pas large (selon votre description) et que ces données ne le rendront pas trop large, je suis d'accord.
HLGEM
4

Étant donné les informations que vous avez fournies et l'objectif étant normalement la normalisation générale, j'ajouterais probablement simplement des colonnes pouvant être annulées, mais vous n'avez pas donné suffisamment d'informations sur la manière dont les données seront utilisées pour savoir quelle est la meilleure façon de les modéliser. est.

Selon la manière dont vous utilisez réellement ces données, vous pouvez envisager un modèle de données différent. Si vous utilisez ces données pour la génération de rapports, vous voudrez peut-être examiner un modèle dimensionnel, qui peut être plus efficace pour certains types de rapports. Par exemple, l'analyse de l'heure du jour fonctionne bien avec une dimension de date et d'heure divisée.

Pour répondre à des questions analytiques, telles que "quel est le moment de la journée le plus populaire pour les visites de campagnes comme X" ou "quel jour d'une campagne voyons-nous le plus de visites par heure", une seule colonne de données de temps ne fonctionne pas très bien (mais cela peut même être scindé dans un modèle relationnel) et il existe de nombreux cas dans lesquels vous pouvez traiter l’adresse IP comme une dimension (peut-être avec une sorte de données géographiques dans un flocon de neige).

Cade Roux
la source