web-dev-qa-db-fra.com

Conception de la base de données: nouvelle table et nouvelles colonnes

(Il a été suggéré de republier ici à partir de StackOverflow)

Ont actuellement une table .. et doivent commencer à y ajouter de nouvelles colonnes de données. Tous les enregistrements (même en allant de l'avant avec de 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 c'est vraiment une extension de certaines des lignes de données et non applicable à chaque ligne.

En d'autres termes, comme il y aura beaucoup de colonnes inutilisées pour ces nouveaux éléments de données, il semble que cela conviendrait mieux à une nouvelle table?

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

 - id 
 - Adresse IP 
 - heures vues 
 - horodatage created_at 
 - date 

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

des champs supplémentaires seraient destinés au suivi du point d'origine (c.-à-d. source/support/campagne google analytics)

Toutes les visites n'auront pas cette information. Je suppose qu'environ 10% des lignes contiendront les données (car elles ne sont généralement attribuées qu'à 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 table unique)

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

38
cgmckeever

Ce avec quoi vous luttez, c'est le partitionnement vertical. Il s'agit d'une technique de conception de base de données physique pour 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 essayez d'optimiser et si cette technique les optimisera. D'un point de vue logique, si ces nouveaux champs dépendent de la clé candidate pour votre entité, ce sont des faits à son sujet qui lui appartiennent. Vous devez d'abord vous assurer de bien comprendre la dépendance fonctionnelle de ces nouveaux champs sur vos clés candidates pour vérifier 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 est une optimisation des performances qui ne doit être effectuée que si elle atteint vos objectifs de performances.

En général, le partitionnement vertical est utile si vous interrogez ces nouvelles colonnes rarement et distinctement des autres colonnes de la table d'origine. En plaçant ces colonnes dans une autre table qui partage le même PK que votre table existante, vous pouvez l'interroger directement lorsque vous voulez ces nouvelles colonnes et obtenir un débit beaucoup plus important car vous aurez beaucoup plus de lignes par page sur le disque pour cette nouvelle table car toutes les colonnes du tableau d'origine ne seront pas placées sur ces lignes. Cependant, si vous interrogerez toujours ces colonnes avec les colonnes de la table d'origine, alors une partition verticale n'aurait pas beaucoup de sens car vous devrez toujours joindre externe pour les obtenir. Les pages des tables sur le disque entrent dans le pool de mémoire tampon d'un SGBD indépendamment, jamais pré-jointes, de sorte que la jointure devra se produire à chaque exécution de requête, même si les données sont épinglées dans le pool de tampons. Dans ce scénario, les transformer en colonnes NULLABLE sur la table d'origine permettrait au moteur de stockage SGBD de les stocker efficacement lorsque NULL et éliminerait le besoin de se joindre lors de la récupération.

Il me semble que votre cas d'utilisation est le dernier et les ajouter en tant que NULLABLE à votre table d'origine est la voie à suivre. Mais comme pour tout le reste dans la conception de la base de données, cela dépend, et pour prendre la bonne décision, vous devez connaître votre charge de travail attendue et sur quoi dépend un bon choix. Un bon exemple de cas d'utilisation approprié pour le partitionnement vertical serait un panneau de recherche de personne, où votre application contient des informations très rarement renseignées sur une personne que quelqu'un pourrait vouloir rechercher, mais rarement. Si vous mettez ces informations dans un autre tableau, vous disposez de bonnes options de performances. Vous pouvez écrire la recherche de sorte que vous ayez 2 requêtes - une qui utilise uniquement les informations principales toujours renseignées (comme le nom de famille ou le ssn), et celle qui externe joint les informations très rarement remplies uniquement lorsqu'elles sont demandées pour la recherche. Ou vous pouvez profiter de l'optimiseur de SGBD s'il est suffisamment intelligent pour reconnaître pour un ensemble donné de variables Host que la jointure externe n'est pas nécessaire et ne l'exécutera pas, et donc vous n'avez qu'à créer 1 requête.

Quelle plateforme de SGBD utilisez-vous? La façon 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 éparses (SQL Server l'a) aura un impact sur la décision. En fin de compte, je recommanderais d'essayer les deux conceptions dans un environnement de test avec des données et une charge de travail de taille production et de voir laquelle atteint le mieux vos objectifs de performance.

29
Todd Everett

Personnellement, je penche pour 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 dans la table d'origine n'occupent pas d'espace, et la nouvelle table a besoin d'une sorte d'identifiant qui compense de toute façon les économies
  • vos requêtes deviennent plus complexes ... where newcolumn is not null devient un left outer join

Dans le tableau unique, cela signifie simplement que la taille de votre ligne peut varier d'une page à l'autre - mais cela ne devrait pas affecter un grand nombre de vos pages existantes, surtout si votre index cluster est sur une colonne à augmentation monotone (identité ou date/heure).

10
Aaron Bertrand

Compte tenu des informations que vous avez fournies, et avec juste l'objectif de normalisation générale, j'ajouterais probablement simplement des colonnes nullables, mais vous n'avez pas donné suffisamment d'informations sur la façon dont les données seront utilisées pour savoir quelle est la meilleure façon de modéliser les données est.

Selon la façon dont vous utilisez réellement ces données, vous pouvez envisager un modèle de données différent. Si vous placez ces données pour la création de rapports, vous souhaiterez peut-être étudier un modèle dimensionnel, qui peut être plus efficace pour certains types de rapports - par exemple, l'analyse de l'heure fonctionne bien avec une dimension de date et d'heure divisée.

Pour répondre à des questions analytiques, telles que "quelle est l'heure la plus populaire de la journée 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 temps de données ne fonctionnera pas très bien (mais cela peut même être divisé dans un modèle relationnel), et il existe de nombreux cas où vous pouvez traiter l'adresse IP comme une dimension (peut-être avec une sorte de données géographiques dans un flocon de neige).

4
Cade Roux