web-dev-qa-db-fra.com

Timeseries: SQL ou NoSQL?

Je ne me soucie pas des différences générales entre SQL et NoSQL (ou leurs différences traditionnelles).

Je cherche actuellement à modifier le stockage de nos séries chronologiques internes. Ils contiennent tous des données financières provenant d'un certain nombre de sources différentes. Actuellement, nous stockons nos données dans une base de données propriétaire. C'est très bien NoSQL, qui a son propre langage de requête.

Je suis intéressé par la contribution de la communauté: comment stockeriez-vous les données dans une base de données SQL? Quels avantages y a-t-il à utiliser SQL sur un NoSQL, en particulier pour les séries chronologiques? Suis-je fou de penser à le stocker dans SQL?

Notre ensemble de données comprend des millions de séries chronologiques, dont environ 10% contiennent chacune des millions d'enregistrements. Les séries chronologiques sont organisées hiérarchiquement:/Marché/Instrument/Valeur/Fréquence, où:

  • Le marché est une bourse de valeurs, etc., essentiellement une collection d'instruments, généralement des instruments similaires.
  • L'instrument est un instrument. Cela pourrait être un indicateur (Brent Crude), une équité (GOOG), etc.
  • La valeur est l'un des multiples types de données d'un instrument. Cela pourrait être proche, haut, bas, etc.
  • La fréquence est la fréquence des valeurs d'une série temporelle particulière. Hebdomadaire, quotidien, mensuel, tick, arbitraire, etc.

Comment les données seraient-elles stockées dans une base de données SQL? Une grande table (peut-être partitionnée par quelque chose), une table par marché ou instrument, une table par série chronologique.

Merci d'avance.

33
Nicolas

En général, pour un tel ensemble de données structuré, je soupçonne que vous pourriez écrire un format de données personnalisé qui était plus rapide pour la plupart des opérations quotidiennes (c'est-à-dire de petites données tirées d'une période arbitraire). L'avantage de passer à un outil de base de données standard est probable dans certains des extras, par exemple les requêtes ad hoc, les accès multiples, la réplication, la disponibilité, etc.

Si on me demandait de créer une base de données pour stocker ces données, je ferais ce qui suit:

Schéma proposé

(1) Les données de base sont placées dans de nombreux (1000) de tables individuelles, chacune contenant deux colonnes:

  1. time: soit un type de données SQL DATETIME ou un type numérique d'une certaine époque (c'est la clé primaire)
  2. valeur: saisie selon vos besoins. Je choisirais par défaut un flottant simple précision, mais un type de données à virgule fixe peut être plus approprié pour les transactions financières. Ceci n'est probablement pas indexé.

Ces tableaux deviendront assez volumineux et vous souhaiterez peut-être les partitionner manuellement par (par exemple) année. Mais vous devrez vérifier les performances du système et régler le cas échéant.

Ces tables ont besoin de noms uniques et il existe deux options. Ils peuvent être lisibles par l'homme (par exemple nyse_goog_dailyhighs_2010) ou (ma préférence) aléatoires. Dans les deux cas, un ensemble de tables de métadonnées est requis et les noms de table aléatoires empêchent les développeurs d'inférer quoi que ce soit dans le nom qui n'était pas censé être déduit.

(2) Les métadonnées sont stockées dans des tableaux séparés, comme requis par l'application :

Une table ou un ensemble de tables supplémentaires est requis pour garder une trace des métadonnées. Ces tableaux contiendront des données sur l'échange, l'instrument, la valeur, la fréquence, les plages de dates, la provenance (d'où proviennent les données), ainsi que tout ce dont vous avez besoin. Ceux-ci sont mappés aux noms de table de données.

S'il y a suffisamment de données, cette recherche pourrait en fait fournir un nom de table et un nom de base de données, permettant une sorte de partage de données auto-implémenté (si c'est l'utilisation correcte du terme). Mais je garderais cela en réserve.

Ensuite, au niveau de la couche application, j'interrogeais les tables de métadonnées pour déterminer où se trouvaient mes données, puis j'exécutais des requêtes relativement simples sur les tables de Big Data pour obtenir mes données.

Avantages:

  • Mon expérience (relativement limitée) est que les bases de données peuvent généralement gérer un grand nombre de petites tables plus facilement qu'un plus petit nombre de grandes tables. Cette approche permet également une maintenance plus facile (par exemple, purger les anciennes données, reconstruire une table corrompue, créer/recharger à partir de sauvegardes, ajouter une nouvelle entité). Cela dissocie complètement les différents types de données, si (par exemple) vous avez des données à des taux différents ou si vous avez besoin de différents types de données.

  • Ce concept de table maigre devrait également permettre un accès rapide au disque pour ce que je soupçonne être la requête la plus courante, une plage contiguë de données provenant d'une seule entité. La plupart des applications de données sont limitées en E/S disque, cela vaut donc la peine d'être considéré. Comme un commentateur l'a déjà laissé entendre, cela peut être une application idéale pour une base de données orientée colonne, mais je n'ai pas encore trouvé de produit orienté colonne suffisamment courant pour que je parie ma carrière. Ce schéma se rapproche assez.

Inconvénients:

  • Environ la moitié de votre espace disque est dédié au stockage des horodatages, alors que franchement les 100 ou 1000 des tables auront les mêmes données exactes dans la colonne d'horodatage. (En fait, c'est une exigence si vous souhaitez effectuer des jointures de table faciles).

  • Le stockage des noms de table et l'exécution de la recherche dynamique nécessitent beaucoup de complexité d'application et d'opérations de chaîne, ce qui me fait grincer des dents. Mais cela semble toujours meilleur que les alternatives (discutées ci-dessous).

Considérations:

  • Attention à l'arrondi dans votre domaine temporel. Vous voulez que vos valeurs soient suffisamment rondes pour activer les jointures (le cas échéant), mais suffisamment précises pour être sans ambiguïté.

  • Faites attention aux fuseaux horaires et à l'heure d'été. Ce sont difficiles à tester. J'imposerais une exigence UTC sur le magasin de données (ce qui pourrait me rendre impopulaire) et gérer les conversions dans l'application.

Variations:

Certaines variations que j'ai envisagées sont:

Pliage des données: Si la série temporelle est également espacée, utilisez une colonne d'horodatage et (par exemple) 10 colonnes de données. L'horodatage fait maintenant référence à l'heure de la première colonne de données, et les autres colonnes de données sont supposées également espacées entre cet horodatage et la suivante. Cela permet d'économiser beaucoup de stockage qui était auparavant utilisé pour stocker des horodatages, au prix d'une complexité de requête et/ou d'application importante. Plage contiguë, les requêtes à entité unique nécessitent désormais moins d'accès au disque.

Multiplexage: Si plusieurs séries temporelles sont connues pour utiliser la même série temporelle, alors utilisez un horodatage et (par exemple) 10 colonnes de données comme décrit ci-dessus . Mais maintenant, chaque colonne représente une série chronologique différente. Cela nécessite une mise à jour de la table de métadonnées, qui n'est pas une recherche dans le nom de table et de colonne. L'espace de stockage est réduit. Les requêtes restent simples. Quelle que soit la portée contiguë, les requêtes à entité unique nécessitent désormais un accès au disque considérablement plus important.

Méga-table: Poussez à l'extrême le concept de "multiplexage" et mettez toutes les données dans une seule table, une fois des séries chronologiques par colonne. Cela nécessite de grandes quantités d'accès au disque pour une plage contiguë, des requêtes d'entité unique et est un cauchemar de maintenance. Par exemple, l'ajout d'une nouvelle entité nécessite désormais une commande MODIFY TABLE sur plusieurs tables TB.

Pour une discussion supplémentaire sur ce format, voir les différentes réponses dans: Trop de colonnes dans MySQL

Table entièrement normalisée: Au lieu d'utiliser de nombreuses tables à 2 colonnes, vous pouvez utiliser une table à trois colonnes, où les colonnes sont time, dataid et valeur. Désormais, vos tables de métadonnées doivent uniquement rechercher des valeurs d'ID, plutôt que des noms de table ou des noms de colonne, ce qui permet d'insérer davantage de logique dans les requêtes SQL, plutôt que dans la couche application.

Environ les 2/3 du stockage sont désormais consommés avec les colonnes de normalisation, ce qui utilisera beaucoup d'espace disque.

Vous pouvez utiliser un ordre de clé primaire de (id_données, horodatage) pour les requêtes rapides à une seule entité contiguë. Ou, vous pouvez utiliser un ordre de clé primaire de (horodatage. Dataid) pour des insertions plus rapides.

Cependant, même après avoir considéré ces variations, mon plan pour mon prochain développement est de nombreux tableaux, deux colonnes chacun. Ça, ou la méthode qui sera bientôt publiée par quelqu'un de plus sage que moi :).

26
Pursuit

Utilisez MongoDB, vous pouvez créer des collections à la volée très rapidement. Regardez comment organiser vos données dans des bases de données distinctes et des collections dans ces bases de données. Considérez la quantité de mémoire dont vous auriez besoin pour essayer de conserver chaque fragment dans la mémoire système - si vous avez besoin d'une récupération rapide. Idiot de s'en tenir à une solution interne, s'il y a quelque chose de plus frais là-bas qui évoluera selon les besoins. Cela ressemble à une bonne initiative.

1
Dantalion