Meilleur magasin de données pour des milliards de lignes

86

J'ai besoin de pouvoir stocker de petits bits de données (environ 50 à 75 octets) pour des milliards d'enregistrements (~ 3 milliards / mois pendant un an).

La seule exigence est des insertions rapides et des recherches rapides pour tous les enregistrements avec le même GUID et la possibilité d'accéder au magasin de données à partir de .net.

Je suis un serveur SQL et je pense que SQL Server peut le faire, mais avec tous les discours sur BigTable, CouchDB et d'autres solutions nosql, cela ressemble de plus en plus à une alternative à un RDBS traditionnel peut-être mieux en raison des optimisations pour requêtes distribuées et mise à l'échelle. J'ai essayé cassandra et les bibliothèques .net ne se compilent pas actuellement ou sont toutes sujettes à changement (avec cassandra lui-même).

J'ai examiné de nombreux magasins de données nosql disponibles, mais je n'en trouve pas qui réponde à mes besoins en tant que plate-forme robuste prête pour la production.

Si vous deviez stocker 36 milliards de petits enregistrements plats pour qu'ils soient accessibles depuis .net, que choisiriez-vous et pourquoi?

Jody Powlette
la source
Ouais, mes chiffres sont corrects. Actuellement, nous avons autant de données qui entrent dans le système, mais nous les agrégons et ne stockons que les décomptes agrégés afin de perdre les données par enregistrement et de ne conserver que les sommes de données horaires. En raison des exigences de l'entreprise, nous souhaitons conserver chaque enregistrement tel qu'il s'est produit à l'origine, soit 3 milliards de lignes / mois.
Jody Powlette
Vous avez soulevé de bonnes questions. Les réponses sont: un temps de fonctionnement de 95% suffit - les données sont déjà retardées d'un montant variable, donc je devrai de toute façon les synchroniser après coup, donc être en panne pendant une courte période n'est pas un facteur décisif. Perdre des inserts ou même des milliers d'inserts n'est pas la fin du monde. Cependant, perdre la valeur d'une journée de données serait plutôt mauvais. La cohérence n'est pas non plus si importante. Fondamentalement, après avoir inséré des lignes 30Mil en une journée, je dois récupérer toutes les lignes avec le même GUID (peut-être 20 lignes) et être raisonnablement sûr de les récupérer toutes.
Jody Powlette
Vidangez-vous 30 millions de lignes par jour dans des tâches par lots planifiées quotidiennement / toutes les heures, ou elles arrivent en flux constant, une à la fois?
Remus Rusanu
Les données arrivent d'un site FTP ... les fichiers arrivent en continu et j'ai un processus qui analyse les fichiers et actuellement il génère les données agrégées et insère les valeurs agrégées (peut-être 1000 lignes) en tant que transaction. Le nouveau processus devra insérer des centaines de milliers de lignes à partir de chaque fichier qui arrive, probablement en utilisant l'insertion en bloc serait le moyen le plus efficace de le faire.
Jody Powlette
Cela ressemble à un travail ETL pour SSIS et SQL Server. Ils détiennent un record du monde pour ETL, à une vitesse de téléchargement de plus de 2 To / heure: blogs.msdn.com/sqlperf/archive/2008/02/27/etl-world-record.aspx
Remus Rusanu

Réponses:

102

Stocker ~ 3,5 To de données et insérer environ 1K / s 24x7, et également interroger à un taux non spécifié, c'est possible avec SQL Server, mais il y a plus de questions:

  • quelle condition de disponibilité avez-vous pour cela? 99,999% de disponibilité, ou est-ce que 95% est suffisant?
  • quelle exigence de fiabilité vous avez? Est-ce que manquer un insert vous coûte 1 M $?
  • quelle exigence de récupérabilité avez-vous? Si vous perdez un jour de données, est-ce important?
  • quelle exigence de cohérence avez-vous? Une écriture doit-elle être garantie pour être visible à la lecture suivante?

Si vous avez besoin de toutes ces exigences que j'ai mises en évidence, la charge que vous proposez coûtera des millions de dollars en matériel et en licences sur un système relationnel, n'importe quel système, quels que soient les gadgets que vous essayez (partitionnement, partitionnement, etc.). Un système nosql, de par sa définition même, ne répondrait pas à toutes ces exigences.

Il est donc évident que vous avez déjà assoupli certaines de ces exigences. Il existe un bon guide visuel comparant les offres nosql basées sur le paradigme `` choisir 2 sur 3 '' dans Visual Guide to NoSQL Systems :

nosql comparisson

Après la mise à jour des commentaires OP

Avec SQL Server, cette implémentation serait simple:

  • une seule clé groupée de table (GUID, heure). Oui, cela va se fragmenter , mais la fragmentation affecte les lectures anticipées et les lectures anticipées ne sont nécessaires que pour les analyses de portée significative. Étant donné que vous ne recherchez que des GUID et une plage de dates spécifiques, la fragmentation n'aura pas beaucoup d'importance. Oui, c'est une clé large, donc les pages non-feuilles auront une densité de clé médiocre. Oui, cela entraînera un mauvais facteur de remplissage. Et oui, des fractionnements de page peuvent se produire. Malgré ces problèmes, compte tenu des exigences, reste le meilleur choix de clé groupée.
  • partitionnez la table par heure afin de pouvoir implémenter une suppression efficace des enregistrements expirés, via une fenêtre glissante automatique . Augmentez cela avec une reconstruction de partition d'index en ligne du mois dernier pour éliminer le faible facteur de remplissage et la fragmentation introduits par le clustering GUID.
  • activer la compression de page. Étant donné que les groupes de clés en cluster par GUID en premier, tous les enregistrements d'un GUID seront côte à côte, ce qui donne à la compression de page une bonne chance de déployer la compression de dictionnaire.
  • vous aurez besoin d'un chemin IO rapide pour le fichier journal. Vous êtes intéressé par un débit élevé, pas par une faible latence pour qu'un journal puisse suivre le rythme de 1K inserts / s, donc le décapage est un must.

Le partitionnement et la compression de page nécessitent chacun un SQL Server Enterprise Edition, ils ne fonctionneront pas sur Standard Edition et les deux sont très importants pour répondre aux exigences.

En remarque, si les enregistrements proviennent d'une ferme de serveurs Web frontaux, je mettrais Express sur chaque serveur Web et au lieu d'INSERER sur le back-end, je mettrais SENDles informations au back-end, en utilisant une connexion / transaction locale sur l'Express co-localisé avec le serveur Web. Cela donne une bien meilleure histoire de disponibilité à la solution.

Voici donc comment je le ferais dans SQL Server. La bonne nouvelle est que les problèmes auxquels vous serez confrontés sont bien compris et que les solutions sont connues. cela ne signifie pas nécessairement que c'est mieux que ce que vous pourriez réaliser avec Cassandra, BigTable ou Dynamo. Je vais laisser quelqu'un de plus compétent dans les choses non-sql-ish pour argumenter leur cas.

Notez que je n'ai jamais mentionné le modèle de programmation, le support .Net et autres. Je pense honnêtement qu'ils ne sont pas pertinents dans les grands déploiements. Ils font une énorme différence dans le processus de développement, mais une fois déployés, peu importe la rapidité du développement, si la surcharge ORM tue les performances :)

Remus Rusanu
la source
J'ai bien lié le site de Nathan, mais ce n'est pas la première page de slashdot;)
Remus Rusanu
@RemusRusanu: analyse de la migration dba.se. Juste pour vous préparer :-) Et +1
gbn
Depuis Microsoft SQL Server 2016, l'édition Entreprise n'est plus requise pour le partitionnement de table car le partitionnement de table est désormais disponible dans presque toutes les éditions de SQL Server 2016.
TChadwick
17

Contrairement aux idées reçues, NoSQL n'est pas une question de performances, ni même d'évolutivité. Il s'agit principalement de minimiser le soi-disant décalage d'impédance objet-relationnel, mais aussi d' évolutivité horizontale par rapport à l' évolutivité verticale plus typique d'un SGBDR.

Pour la simple exigence d'insertions rapides et de recherches rapides, presque tous les produits de base de données feront l'affaire. Si vous souhaitez ajouter des données relationnelles ou des jointures, ou si vous avez une logique transactionnelle complexe ou des contraintes à appliquer, vous voulez une base de données relationnelle. Aucun produit NoSQL ne peut être comparé.

Si vous avez besoin de données sans schéma, vous voudrez utiliser une base de données orientée document telle que MongoDB ou CouchDB. Le schéma lâche est le principal attrait de ceux-ci; Personnellement, j'aime MongoDB et je l'utilise dans quelques systèmes de rapports personnalisés. Je trouve cela très utile lorsque les exigences en matière de données changent constamment.

L'autre option NoSQL principale est les magasins de valeurs-clés distribués tels que BigTable ou Cassandra. Celles-ci sont particulièrement utiles si vous souhaitez mettre à l'échelle votre base de données sur de nombreuses machines exécutant du matériel de base. Ils fonctionnent bien sur les serveurs aussi, évidemment, mais ne tirent pas parti du matériel haut de gamme ainsi que de SQL Server ou Oracle ou d'une autre base de données conçue pour la mise à l' échelle verticale , et évidemment, ils ne sont pas relationnels et ne sont pas bons pour appliquer la normalisation. ou des contraintes. De plus, comme vous l'avez remarqué, la prise en charge de .NET a tendance à être au mieux inégale.

Tous les produits de base de données relationnelle prennent en charge le partitionnement d'un type limité. Ils ne sont pas aussi flexibles que BigTable ou d'autres systèmes DKVS, ils ne se partitionnent pas facilement sur des centaines de serveurs, mais il ne semble vraiment pas que ce soit ce que vous recherchez. Ils sont assez bons pour gérer le nombre d'enregistrements dans les milliards, tant que vous indexez et normalisez correctement les données, exécutez la base de données sur du matériel puissant (en particulier les SSD si vous pouvez vous le permettre), et partitionnez sur 2 ou 3 ou 5 disques physiques si nécessaire.

Si vous répondez aux critères ci-dessus, si vous travaillez dans un environnement d'entreprise et que vous avez de l'argent à dépenser pour du matériel décent et une optimisation de base de données, je m'en tiendrai à SQL Server pour le moment. Si vous pincez quelques centimes et que vous devez l'exécuter sur du matériel de cloud computing Amazon EC2 bas de gamme, vous voudrez probablement opter pour Cassandra ou Voldemort à la place (en supposant que vous puissiez travailler avec .NET).

Aaronaught
la source
11

Très peu de gens travaillent à la taille de l'ensemble de plusieurs milliards de lignes, et la plupart du temps, je vois une demande comme celle-ci lors d'un débordement de pile, les données ne sont pas proches de la taille pour laquelle elles sont signalées.

36 milliards, 3 milliards par mois, soit environ 100 millions par jour, 4,16 millions par heure, ~ 70 000 lignes par minute, 1,1 000 lignes par seconde entrant dans le système, de manière soutenue pendant 12 mois, sans temps d'arrêt.

Ces chiffres ne sont pas impossibles de loin, j'ai fait des systèmes plus grands, mais vous voulez vérifier que ce sont vraiment les quantités que vous voulez dire - très peu d'applications ont vraiment cette quantité.

En termes de stockage / récupération et un aspect assez critique que vous n'avez pas mentionné est le vieillissement des données plus anciennes - la suppression n'est pas gratuite.

La technologie habituelle est le partitionnement, cependant, la recherche / extraction basée sur le GUID entraînerait de mauvaises performances, en supposant que vous deviez obtenir chaque valeur correspondante sur toute la période de 12 mois. Vous pouvez placer un index clusterisé sur la colonne GUID pour obtenir votre cluster de données associé en lecture / écriture, mais à ces quantités et à cette vitesse d'insertion, la fragmentation sera beaucoup trop élevée pour être prise en charge et tombera par terre.

Je suggérerais également que vous aurez besoin d'un budget matériel très décent s'il s'agit d'une application sérieuse avec des vitesses de réponse de type OLTP, c'est-à-dire par des suppositions approximatives, en supposant très peu de frais généraux d'indexation, environ 2,7 To de données.

Dans le camp SQL Server, la seule chose que vous voudrez peut-être examiner est la nouvelle édition de l'entrepôt de données parallèle (madison), qui est davantage conçue pour partitionner les données et exécuter des requêtes parallèles pour fournir une vitesse élevée contre les grands datamarts.

Andrew
la source
3
En bioinformatique, les ensembles de données d'un milliard de lignes ne sont pas rares. Mais ils sont souvent traités de manière purement continue à partir de fichiers plats.
Erik Garrison
3
@Erik: pour le traitement des flux (c'est-à-dire juste besoin de détecter certaines conditions, mais il n'est pas nécessaire de stocker les données pour une requête ultérieure) quelque chose comme StreamInsight est meilleur que n'importe quelle base de données microsoft.com/sqlserver/2008/en/us/r2 -complex-event.aspx
Remus Rusanu
2

«J'ai besoin de pouvoir stocker de petits morceaux de données (environ 50 à 75 octets) pour des milliards d'enregistrements (~ 3 milliards / mois pendant un an).

La seule exigence est des insertions rapides et des recherches rapides pour tous les enregistrements avec le même GUID et la possibilité d'accéder au magasin de données à partir de .net. "

Je peux vous dire par expérience que cela est possible dans SQL Server, car je l'ai fait au début de 2009 ... et cela fonctionne encore à ce jour et assez rapidement.

La table a été partitionnée en 256 partitions, gardez à l'esprit qu'il s'agissait de la version SQL de 2005 ... et nous avons fait exactement ce que vous dites, c'est-à-dire stocker des informations par GUID et récupérer rapidement par GUID.

Quand je suis parti, nous avions environ 2 à 3 milliards d'enregistrements et la récupération des données était encore assez bonne (1 à 2 secondes si via l'interface utilisateur, ou moins si sur le SGBDR) même si la politique de conservation des données était sur le point d'être instanciée.

Donc, pour faire court, j'ai pris le 8ème caractère (c'est-à-dire quelque part au milieu) de la chaîne GUID et SHA1 l'a haché et converti en minuscule int (0-255) et stocké dans la partition appropriée et utilisé le même appel de fonction lors de l'obtention les données de retour.

envoyez-moi un ping si vous avez besoin de plus d'informations ...

Goran B.
la source
2

L'article suivant décrit l'importation et l'utilisation d'une table de 16 milliards de lignes dans Microsoft SQL. http://sqlmag.com/t-sql/adventures-big-data-how-import-16-billion-rows-single-table .

De l'article:

Voici quelques conseils tirés de mon expérience:

  • Plus vous avez de données dans une table avec un index cluster défini, plus il est lent à y importer des enregistrements non triés. À un moment donné, cela devient trop lent pour être pratique.
  • Si vous souhaitez exporter votre table dans le plus petit fichier possible, faites-en un format natif. Cela fonctionne mieux avec les tables contenant principalement des colonnes numériques, car elles sont représentées de manière plus compacte dans des champs binaires que des données de caractères. Si toutes vos données sont alphanumériques, vous ne gagnerez pas grand-chose à les exporter au format natif. Ne pas autoriser les valeurs nulles dans les champs numériques peut encore compacter les données. Si vous autorisez un champ à être nullable, la représentation binaire du champ contiendra un préfixe de 1 octet indiquant le nombre d'octets de données qui suivront.
  • Vous ne pouvez pas utiliser BCP pour plus de 2 147 483 647 enregistrements car la variable de compteur BCP est un entier de 4 octets. Je n'ai trouvé aucune référence à cela sur MSDN ou sur Internet. Si votre table contient
    plus de 2 147 483 647 enregistrements, vous devrez l'exporter par blocs
    ou écrire votre propre routine d'exportation.
  • La définition d'un index clusterisé sur une table préremplie prend beaucoup d'espace disque. Dans mon test, mon journal a explosé à 10 fois la
    taille de la table d' origine avant la fin.
  • Lors de l'importation d'un grand nombre d'enregistrements à l'aide de l'instruction BULK INSERT, incluez le paramètre BATCHSIZE et spécifiez le nombre d'
    enregistrements à valider à la fois. Si vous n'incluez pas ce paramètre,
    votre fichier entier est importé en une seule transaction, ce qui
    nécessite beaucoup d'espace de journal.
  • Le moyen le plus rapide d'obtenir des données dans une table avec un index clusterisé consiste à effectuer un tri préalable des données. Vous pouvez ensuite l'importer à l'aide de l'
    instruction BULK INSERT avec le paramètre ORDER.
Charles Burns
la source
1

Il y a un fait inhabituel qui semble ignoré.

" Fondamentalement, après avoir inséré 30 mil lignes en un jour, je dois récupérer toutes les lignes avec le même GUID (peut-être 20 lignes) et être raisonnablement sûr de les récupérer toutes "

Ne nécessitant que 20 colonnes, un index non cluster sur le GUID fonctionnera très bien. Vous pouvez regrouper sur une autre colonne pour la dispersion des données entre les partitions.

J'ai une question concernant l'insertion des données: comment sont-elles insérées?

  • S'agit-il d'un encart en vrac selon un certain horaire (par minute, par heure, etc.)?
  • De quelle source ces données sont-elles extraites (fichiers plats, OLTP, etc.)?

Je pense qu'il faut répondre à ces questions pour aider à comprendre un côté de l'équation.

Josef Richberg
la source
1

Amazon Redshift est un excellent service. Elle n'était pas disponible lorsque la question a été initialement publiée en 2010, mais elle est maintenant un acteur majeur en 2017. C'est une base de données basée sur des colonnes, dérivée de Postgres, donc les bibliothèques de connecteurs SQL et Postgres standard fonctionneront avec elle.

Il est préférable de l'utiliser à des fins de reporting, en particulier pour l'agrégation. Les données d'une seule table sont stockées sur différents serveurs dans le cloud d'Amazon, distribuées par les distkeys de table définis, de sorte que vous comptez sur la puissance du processeur distribué.

Ainsi, les SELECT et en particulier les SELECT agrégés sont rapides comme l'éclair. Le chargement de données volumineuses doit être de préférence effectué avec la commande COPY à partir des fichiers csv Amazon S3. Les inconvénients sont que les suppressions et les mises à jour sont plus lentes que d'habitude, mais c'est pourquoi Redshift n'est pas principalement une base de données transnationale, mais plutôt une plate-forme d'entrepôt de données.

Martin Taleski
la source
0

Vous pouvez essayer d'utiliser Cassandra ou HBase, mais vous devrez vous renseigner sur la façon de concevoir les familles de colonnes selon votre cas d'utilisation. Cassandra fournit son propre langage de requête, mais vous devez utiliser les API Java de HBase pour accéder directement aux données. Si vous devez utiliser Hbase, je vous recommande d'interroger les données avec Apache Drill à partir de Map-R qui est un projet Open Source. Le langage de requête de Drill est conforme à SQL (les mots-clés de drill ont la même signification qu'ils auraient en SQL).

Yayati Sule
la source
0

Avec autant de disques par an, vous allez finir par manquer d'espace. Pourquoi pas le stockage du système de fichiers comme xfs qui prend en charge 2 ^ 64 fichiers et utilise des boîtes plus petites. Indépendamment de la fantaisie que les gens veulent obtenir ou du montant d'argent que l'on finirait par dépenser pour obtenir un système avec n'importe quelle base de données SQL NoSQL ... quels que soient ces nombreux enregistrements sont généralement réalisés par des sociétés électriques et des stations météorologiques / fournisseurs comme le ministère de l'environnement qui contrôlent les plus petits stations dans tout le pays. Si vous faites quelque chose comme le stockage de la pression .. température .. vitesse du vent .. humidité etc ... et guid est l'emplacement .. vous pouvez toujours diviser les données par année / mois / jour / heure. En supposant que vous stockiez 4 ans de données par disque dur. Vous pouvez ensuite le faire fonctionner sur un Nas plus petit avec un miroir où il offrirait également de meilleures vitesses de lecture et plusieurs points de montage. en fonction de l'année de sa création. Vous pouvez simplement créer une interface Web pour les recherches. So dumping location1 / 2001/06/01 // température et localisation1 / 2002/06/01 // temperature ne viderait que le contenu de la température horaire pour le 1er jour de l'été au cours de ces 2 années (24h * 2) 48 petits fichiers vs la recherche d'une base de données avec des milliards d'enregistrements et éventuellement des millions dépensés. Une manière simple de voir les choses. 1,5 milliard de sites Web dans le monde avec Dieu sait combien de pages chacun Si une entreprise comme Google devait dépenser des millions pour 3 milliards de recherches pour payer des super-ordinateurs pour cela, elle serait fauchée. Au lieu de cela, ils ont la facture d'électricité ... quelques millions d'ordinateurs de merde. Et l'indexation de la caféine ... à l'épreuve du temps ... Continuez à en ajouter. Et ouais, où l'indexation exécutée à partir de SQL a du sens, alors c'est génial Construire des super-ordinateurs pour des tâches de merde avec des choses fixes comme la météo ... des statistiques et ainsi de suite afin que les techniciens puissent se vanter que leurs systèmes croquent xtb en x secondes ... gaspillage d'argent qui peut être passé ailleurs ..

Francisco
la source
-2

Stocker les enregistrements dans des fichiers binaires simples, un fichier par GUID, ne serait pas plus rapide que cela.

Thomas Kjørnes
la source
5
Vous attendez-vous vraiment à ce que cela fonctionne bien?
ChaosPandion
3
Oui, la création de milliards de fichiers sur un système de fichiers peut être dévastatrice pour certains systèmes de fichiers. J'ai fait l'erreur de faire quelque chose comme ça, mais avec seulement 1 million et j'ai pratiquement arrêté le système en essayant d'ouvrir un shell dans l'un de ces dossiers. De plus, à moins que vous ne recherchiez basé sur un guide, comment le mécanisme de requête est-il censé fonctionner?
Rob Goodwin
Il est difficile de deviner comment cela fonctionnerait sans savoir combien de GUID uniques sont attendus :) Mais cela n'est pas plus simple que d'écrire dans des fichiers simples. Et les insertions rapides avec la recherche par GUID étaient la seule exigence.
Thomas Kjørnes
Cela peut fonctionner mais vous devez limiter le nombre de fichiers par dossier. Vous devez générer un nouveau dossier pour n fichiers. Vous pouvez utiliser une sous-chaîne du guid comme nom de dossier.
TTT
1
oui, il y a une limite sur le nombre d'inodes pour beaucoup de systèmes de fichiers et je me souviens avoir atteint cette limite sur le système de fichiers redhat par défaut ... la limite était d'environ 1 000 000 fichiers.
Dean Hiller
-3

Vous pouvez utiliser MongoDB et utiliser le guid comme clé de partitionnement, cela signifie que vous pouvez distribuer vos données sur plusieurs machines, mais les données que vous souhaitez sélectionner ne se trouvent que sur une seule machine car vous sélectionnez par la clé de partitionnement.

Le partage dans MongoDb n'est pas encore prêt pour la production.

Théo
la source