Quelle est la bonne façon de stocker un grand nombre de colonnes?

18

J'ai un problème pour décider comment stocker ces données dans ma base de données. Des suggestions sur la meilleure façon de le faire? Je ne connais pas grand-chose aux bases de données, je pourrais ajouter.

J'ai des données formatées comme ceci, mais plutôt que 4, le nombre de colonnes est d'environ 240, donc chaque date a 240 valeurs uniques qui lui sont associées:

Date/Time 200,00 202,50 205,00  
2010.11.12  13:34:00  45,8214 43,8512  41,5369   
2010.11.12  13:35:00  461,9364  454,2612  435,5222 

En outre, les lignes sont associées aux DataSites.

Ma première pensée a été d'avoir une table comme celle-ci: DataID (pk), DataSiteID, ParameterID, Date, Value, avec un index sur DataSite, Parameter et Date. Le ParameterID fait référence à une autre table qui stocke les en-têtes de colonne d'entrée (200,00 202,50 205,00 ...).

Ma deuxième pensée était simplement d'avoir un tableau avec toutes les 240 colonnes impaires. J'ai trouvé quelques autres moyens, mais ils sont également assez insatisfaisants.

Le problème que j'ai avec ma première solution (pas un problème si énorme, mais je ne l'aime pas), c'est que la date et le DataSiteID vont être répétés pour les 240 valeurs de cette ligne d'entrée, donc il en utilise un peu d'espace supplémentaire.

Il y aura environ 40 Go de données par an à venir (dans le format de texte ci-dessus), et les données seront recherchées par DataSite, Parameter et Date. La quantité de données entrant quadruplera très probablement dans un an environ.

Des bonnes idées? Merci, James

modifier: Il s'agit de données de séries chronologiques, les colonnes étant des mesures à différentes longueurs d'onde. Les données devront être analysées dans une gamme relativement étroite de longueurs d'onde. Il pourrait également y avoir des longueurs d'onde supplémentaires ajoutées à un moment donné dans le futur.

edit: Merci pour les réponses, je l'apprécie vraiment :) Je pense que je peux probablement trouver le temps d'exécuter quelques expériences avec environ 500 Go de données de test. Je reviendrai avec toutes les conclusions;)

James
la source
2
Je suppose, d'après le nom des colonnes, qu'il s'agit d'une sorte de données de séries chronologiques d'observation. S'il s'agit de données scientifiques, j'essaierais de voir si la discipline scientifique a des moyens typiques d'organiser leurs données, ou à tout le moins, quels sont les cas d'utilisation scientifique qui utilisent les données.
Joe
Il s'agit bien de données chronologiques :) post original édité avec un peu plus d'informations.
James

Réponses:

10

Vous pouvez faire un cas de toute façon, mais si les données vont être utilisées pour l'analyse et que vous souhaitez souvent voir plusieurs colonnes de ces données en même temps, utilisez le tableau large. Assurez-vous de connaître la quantité de colonnes et les limites de taille de ligne de vos bases de données. Assurez-vous d'avoir les bons types de données. Si de nombreuses colonnes sont nulles, SQL Server vous permet d'optimiser la table pour cela. Vous pouvez également envisager d'utiliser une solution NOSQL (Not Only SQL) pour l'analyse de ce type de données.

Si ces données vont être moindres pour l'analyse, vous voudrez peut-être les normaliser comme indiqué dans votre question.

Eric Humphrey - lotsahelp
la source
6

J'ai eu une situation très similaire à la vôtre, 257 champs avec 30 à 50 Go par an entrant. J'ai fini par rester simple, une longue grande table de garçon dans SQL Server. Mes données ont été assez bien interrogées mais principalement sur la date et cela a bien fonctionné.

J'aurais pu diviser les données en mandrins logiques plus petits (groupes de 50 environ), mais dans ce cas, il n'y avait vraiment pas beaucoup d'avantages, alors je me suis évité la peine.

Si je me sentais à la mode maintenant, je pourrais envisager une option NoSQL qui est mieux adaptée en théorie, mais avec des données critiques pour la mission, essayer de nouvelles choses n'est pas toujours génial pour les nerfs.

henry.oswald
la source
6

Donc, pour répondre tardivement à ma propre question (le projet n'a jamais été mené à terme), quand j'ai réussi à gagner du temps, j'ai rempli une table de test avec 500 Go de données avec la table disposée comme suit:

Ma première pensée a été d'avoir une table comme celle-ci: DataID (pk), DataSiteID, ParameterID, Date, Value, avec un index sur DataSite, Parameter et Date. Le ParameterID fait référence à une autre table qui stocke les en-têtes de colonne d'entrée (200,00 202,50 205,00 ...).

La configuration de la base de données était l'installation standard de PostgreSQL sur une ancienne machine double cœur avec 3 Go de RAM. J'ai exécuté environ une douzaine de requêtes différentes en sélectionnant simplement les données par DataSite Date et ParameterID, en faisant la moyenne des données sur une période de 1 heure, une période de 1 jour et en insérant de nouveaux morceaux de données. De mémoire, toutes les requêtes ont pris moins d'une seconde pour s'exécuter. C'était certainement beaucoup plus rapide que prévu et tout à fait utilisable. Une chose à laquelle je n'avais pas pensé était qu'avec la table indexée de cette façon, le fichier d'index était également de près de 500 Go, donc avoir une table de 240 colonnes à la place économiserait certainement beaucoup d'espace disque.

James
la source
Mais tout en économisant de l'espace, cela aurait certainement affecté la vitesse d'indexation. Vous pouvez réessayer si vous en avez l'occasion et aller de l'avant et le faire pivoter.
jcolebrand
3

Dans Postgres, je résoudrais élégamment cela avec un type de tableau ou un varray dans Oracle.

Gaius
la source
Cela fonctionnerait, le seul inconvénient est que je devrais stocker les en-têtes de colonne pour ce DataSite quelque part, car sans lui, les données ne signifient rien, et elles pourraient varier / changer (elles ne sont pas censées le faire, mais je '' J'ai vu des cochons voler avant ...)
James
Dans ce cas, dans ma table de données principale, j'aurais une autre colonne appelée "version" et une autre version de mappage de table avec un tableau d'en-têtes de colonne (de sorte que les index du tableau correspondent au tableau de données).
Gaius
3

Je ne sais pas si c'est utile pour votre problème, mais pour les colonnes, je n'ai pas besoin de faire de demandes directes (cols que je n'ai jamais mis dans ma condition WHERE), et qui ne sont informatifs que lorsque je veux toutes les informations sur certains des lignes spécifiques, je les combine dans un champ de blog au format JSON.


la source
En outre, compressez cette goutte. Effectuez la compression dans le client, afin de ne pas ajouter de charge sur le réseau et le serveur.
Rick James
2

Je prendrais probablement la décision finale de la conception en fonction de la distribution des paramètres_id interrogés. Autrement dit, s'il y a quelques paramètres_id qui sont interrogés presque exclusivement, je mettrais leurs valeurs dans une table chaude et les valeurs restantes dans une autre table froide .

Otoh, si leur distribution de requête est plus ou moins égale, je chargerais un jeu d'échantillons valant quelques jours dans une table où l'on enregistre toutes les valeurs afin de voir quel est le rapport entre les enregistrements / blocs de base de données (ou si il y a même un problème de chaînage , ce qui est probable). En fonction de cela, je prendrais alors une autre décision de conception.

Eh bien, après l'avoir lu, je ferais probablement les deux approches pour une dessicion en parallèle.

René Nyffenegger
la source
2

Je relisais la question - si j'ai bien compris, alors dans chaque enregistrement que vous obtenez en entrée, il y a différentes valeurs suivies (basées sur le ParameterID):

Le ParameterID fait référence à une autre table qui stocke les en-têtes de colonne d'entrée (200,00 202,50 205,00 ...).

... Je ne sais pas assez comment vous interagissez avec les données, mais je serais enclin à opter pour une autre option - avoir une table séparée pour chaque ID de paramètre, puis si nécessaire avoir une vue qui joindre les différents paramètres différents par date et emplacement dans le tableau plus large (240 colonnes); s'il était important de garder le DataID accessible dans la vue, alors vous pourriez utiliser un UNIONplutôt qu'un a JOIN, mais les colonnes seront peu peuplées.

Joe
la source
Par paramètre, j'entends l'en-tête de colonne, ou longueur d'onde. J'avais pensé à le faire de cette façon, mais avoir 240 tables semble un peu maladroit :)
James
@James ... il ne devrait pas y avoir 240 tables ... seulement autant que les ParameterIDs uniques . La vue serait alors aussi large que le nombre de longueurs d'onde discrètes sur lesquelles vous avez des mesures (plus les variables indépendantes). ... Vous voudrez peut-être voir comment la communauté OPeNDAP gère les choses, car elles sont orientées vers les données de séries chronologiques. La plupart des données que je traite sont des images (télescope, coronographe, magnétographe), donc leurs trucs ne correspondent pas à mon travail, donc je ne sais pas comment ils gèrent le stockage. (il peut s'agir simplement de tables HDF / CDF / NetCDF / ASCII).
Joe
Malheureusement, il existe des paramètres uniques de 240 ish :( Merci pour le lien :)
James
@James: aussi, est-ce des données d'irradiance? Si oui, vous voudrez peut-être demander aux gens de LISIRD ... Je pense qu'ils les séparent en ensembles de données séparés par expérience, et je ne sais pas s'ils les conservent dans des bases de données ou simplement des fichiers plats.
Joe