MySQL peut-il raisonnablement effectuer des requêtes sur des milliards de lignes?

283

Je prévois de stocker les analyses d'un spectromètre de masse dans une base de données MySQL et je voudrais savoir si le stockage et l'analyse de cette quantité de données sont réalisables à distance. Je sais que les performances varient énormément en fonction de l'environnement, mais je recherche un ordre de grandeur approximatif: les requêtes prendront-elles 5 jours ou 5 millisecondes?

Format d'entrée

Chaque fichier d'entrée contient une seule exécution du spectromètre; chaque exécution comprend un ensemble d'analyses et chaque analyse comporte un tableau ordonné de points de données. Il y a un peu de métadonnées, mais la majorité du fichier est composée de tableaux de 32 ou 64 bits ou flottants.

Système hôte

| ---------------- + ------------------------------- |
| OS | Windows 2008 64 bits |
| Version de MySQL | 5.5.24 (x86_64) |
| CPU | 2x Xeon E5420 (total de 8 noyaux) |
| RAM | 8 Go |
| Système de fichiers SSD | 500 GiB |
| HDD RAID | 12 TiB |
| ---------------- + ------------------------------- |

Certains services exécutés sur le serveur utilisent un temps de traitement négligeable.

Fichier statistique

| ------------------ + -------------- |
| nombre de fichiers | ~ 16 000 |
| taille totale | 1,3 TiB |
| taille min | 0 octet |
| taille maximale | 12 GiB |
| moyenne | 800 MiB |
| médiane | 500 Mio |
| points de données totaux | ~ 200 milliards |
| ------------------ + -------------- |

Le nombre total de points de données est une estimation très approximative.

Schéma proposé

Je prévois de faire les choses «correctement» (c’est-à-dire de normaliser les données de manière folle) et d’avoir un runstableau, un spectratableau avec une clé étrangère runset un datapointstableau avec une clé étrangère spectra.

La question des 200 milliards de points de données

Je vais analyser plusieurs spectres et éventuellement plusieurs analyses, ce qui entraînera des requêtes pouvant toucher des millions de lignes. En supposant que j'indexe tout correctement (ce qui est un sujet pour une autre question) et que je n'essaye pas de mélanger des centaines de MiB sur le réseau, est-il plausible à distance pour MySQL de gérer cela?

information additionnelle

Les données de numérisation proviendront de fichiers au format XML XML . La viande de ce format est dans les <binaryDataArrayList>éléments où les données sont stockées. Chaque analyse produit> = 2 <binaryDataArray>éléments qui, pris ensemble, forment un tableau à 2 dimensions (ou plus) de la forme [[123.456, 234.567, ...], ...].

Ces données sont écrites une seule fois. Les performances de mise à jour et la sécurité des transactions ne sont donc pas un sujet de préoccupation.

Mon plan naïf pour un schéma de base de données est le suivant:

runs table

| nom de colonne | type |
| ------------- + ------------- |
| id | CLÉ PRIMAIRE |
| heure_départ | TIMESTAMP |
| nom | VARCHAR |
| ------------- + ------------- |

spectra table

| nom de colonne | type |
| ---------------- + ------------- |
| id | CLÉ PRIMAIRE |
| nom | VARCHAR |
| index | INT |
| spectre_type | INT |
| représentation | INT |
| run_id | CLÉ ÉTRANGÈRE |
| ---------------- + ------------- |

datapoints table

| nom de colonne | type |
| ------------- + ------------- |
| id | CLÉ PRIMAIRE |
| spectre_id | CLÉ ÉTRANGÈRE |
| mz | DOUBLE |
| num_counts | DOUBLE |
| index | INT |
| ------------- + ------------- |

Est-ce raisonnable?


Ainsi, comme vous l'avez peut-être pu déduire, je suis le programmeur, pas le biologiste du laboratoire. Je ne connais donc pas la science aussi bien que les scientifiques.

Voici un graphique d'un seul spectre (scan) du type de données avec lequel je vais traiter:

Capture d'écran de la visionneuse

Le logiciel a pour objectif de déterminer où et comment les pics sont importants. Nous utilisons un logiciel propriétaire pour comprendre cela maintenant, mais nous voulons écrire notre propre programme d'analyse (en R) afin de savoir ce qui se passe sous les feuilles. Comme vous pouvez le constater, la grande majorité des données ne sont pas intéressantes, mais nous ne voulons pas rejeter les données potentiellement utiles que notre algorithme a manquées. Une fois que nous aurons une liste de pics probables dont nous serons satisfaits, le reste du pipeline utilisera cette liste de pics plutôt que la liste brute de points de données. Je suppose qu'il suffirait de stocker les points de données bruts sous forme de gros blob pour pouvoir les ré-analyser au besoin, mais ne conserver que les pics sous forme d'entrées de base de données distinctes. Dans ce cas, il y aurait seulement une vingtaine de pics par spectre, donc les trucs délirants de la mise à l'échelle ne devraient pas

haxney
la source
8
Puisqu'il s'agit de données brutes de spectromètre de masse à interrogation A / D, il semble vraiment stupide de les stocker dans la base de données. Je prenais mes données brutes, les vidais, les traitais et stockais les RÉSULTATS traités dans une base de données. Les résultats seraient (a) les formes d'onde stockées une forme d'onde par ligne, (b) d'autres données associées à ces formes d'onde, telles que les courbes d'étalonnage, et (c) les lignes de résultats de la base de données. Cela réduirait des milliards de rangées de ballonnements de votre conception. Lorsque vous souhaitez réexécuter une analyse initiale, vous devez effectivement modifier certains paramètres, exécuter une opération de calcul géant et stocker les nouveaux résultats dans la base de données.
Warren P

Réponses:

115

Je ne connais pas très bien vos besoins, mais peut-être que stocker chaque point de données dans la base de données est un peu excessif. Cela ressemble presque à une approche consistant à stocker une bibliothèque d’images en stockant chaque pixel en tant qu’enregistrement séparé dans une base de données relationnelle.

En règle générale, le stockage de données binaires dans des bases de données est la plupart du temps incorrect. Il y a généralement un meilleur moyen de résoudre le problème. Bien qu'il ne soit pas fondamentalement erroné de stocker des données binaires dans une base de données relationnelle, les inconvénients l'emportent souvent sur les gains. Les bases de données relationnelles, comme son nom l'indique, conviennent mieux au stockage de données relationnelles. Les données binaires ne sont pas relationnelles. Cela ajoute de la taille (souvent de manière significative) aux bases de données, peut nuire aux performances et peut poser des questions sur la maintenance d'instances MySQL comportant des milliards d'enregistrements. La bonne nouvelle est qu’il existe des bases de données particulièrement bien adaptées au stockage de données binaires. L’un d’eux, bien que pas toujours évident, est votre système de fichiers! Il suffit de créer une structure de nommage des répertoires et des fichiers pour vos fichiers binaires,

Une autre approche consisterait à utiliser un système de stockage basé sur des documents pour vos données de points de données (et peut-être de spectres) et à utiliser MySQL pour les analyses (ou peut-être de placer les analyses dans le même DB que les autres).

Krystian Cybulski
la source
5
Pourquoi est-il mal considéré de stocker des données binaires dans une base de données? (Demander en partie parce que je suis curieux mais aussi parce que je peux penser à un cas d'utilisation.)
15
Si les données binaires n'ont pas de valeur individuellement, elles ne doivent pas être stockées comme une ligne unique. Pixel 500x325 sur une image est sans importance.
1
C'est un très bon point. Nous devrions probablement conserver les fichiers bruts au cas où nous aurions besoin de les extraire plus tard, mais l'analogie avec le stockage des images est excellente. Nous n’aurons jamais besoin d’accéder à chaque point de données (à moins que nous ne reprenions l’extraction des pics), il serait donc préférable de stocker les informations statistiques extraites.
haxney
107

J'ai déjà travaillé avec une très grande base de données MySQL (Terabyte +). La plus grande table que nous avions avait littéralement plus d'un milliard de lignes. Cela utilisait MySQL 5.0, il est donc possible que les choses se soient améliorées.

Ça a marché. MySQL a traité les données correctement la plupart du temps. C'était extrêmement difficile à manier. (Si vous souhaitez une disponibilité de six niveaux sigma avec un téraoctet de données, n'utilisez pas MySQL. Nous étions une startup qui ne disposait d'aucun DBA et de fonds limités.)

Juste sauvegarder et stocker les données était un défi. Il faudrait des jours pour restaurer la table si nous en avions besoin.

Nous avons eu de nombreuses tables dans la gamme de 10-100 millions de lignes. Toute participation significative aux tables demandait trop de temps et prendrait une éternité. Nous avons donc écrit des procédures stockées pour «parcourir» les tables et traiter les jointures par rapport à des plages d'ID. De cette façon, nous traiterions les données 10 à 100 000 lignes à la fois (joindre contre 1 à 100 000 id, puis 100 001 à 200 000, etc.). C'était nettement plus rapide que de rejoindre la table entière.

L'utilisation d'index sur des tables très volumineuses qui ne sont pas basées sur la clé primaire est également beaucoup plus difficile. Mysql 5.0 stocke les index en deux parties: il stocke les index (autres que l'index primaire) en tant qu'index des valeurs de clé primaire. Les recherches indexées se font donc en deux parties: d’abord, MySQL passe à un index et en extrait les valeurs de clé primaire qu’il doit rechercher, puis effectue une seconde recherche sur l’index de clé primaire pour trouver où se trouvent ces valeurs.

En résumé, pour les très grandes tables (1 à 200 millions de lignes et plus), l'indexation par rapport aux tables est plus restrictive. Vous avez besoin de moins d'index plus simples. Et même des déclarations select simples qui ne sont pas directement sur un index peuvent ne jamais revenir. Où les clauses doivent atteindre les index ou les oublier.

Mais tout cela étant dit, les choses ont vraiment fonctionné. Nous avons pu utiliser MySQL avec ces très grands tableaux et faire des calculs et obtenir des réponses correctes.

Tenter une analyse sur 200 milliards de lignes de données nécessiterait du matériel de très haut de gamme, une grande réactivité et de la patience. Garder les données sauvegardées dans un format que vous pourriez restaurer serait un travail important.

Je suis d'accord avec la réponse de srini.venigalla selon laquelle la normalisation des données comme une folle n'est peut-être pas une bonne idée ici. Faire des jointures sur plusieurs tables avec autant de données vous exposera au risque de tri des fichiers, ce qui pourrait empêcher certaines de vos requêtes de revenir. Dénormalliser avec des clés simples et entières vous donnerait une meilleure chance de succès.

Tout ce que nous avions était InnoDB. En ce qui concerne MyISAM vs InnoDB: Le principal serait de ne pas mélanger les deux. Vous ne pouvez pas vraiment optimiser un serveur pour les deux, à cause de la façon dont MySQL met en cache les clés et autres données. Choisissez l'une ou l'autre pour toutes les tables d'un serveur si vous le pouvez. MyISAM peut aider à résoudre certains problèmes de rapidité, mais peut ne pas aider le travail de base de DBA qui doit être effectué - ce qui peut être mortel.

Kevin Bedell
la source
1
MySQL a beaucoup progressé dans le service des index (...) depuis la version 5.0. Il serait intéressant de voir comment il se comporte maintenant.
Bague Ø
70

normaliser les données comme un fou

Normaliser les données comme un fou peut ne pas être la bonne stratégie dans ce cas. Gardez vos options ouvertes en stockant les données à la fois sous la forme normalisée et également sous la forme de vues matérialisées hautement adaptées à votre application. La clé dans ce type d'applications N'écrit PAS des requêtes ad hoc. La modélisation des requêtes est plus importante que la modélisation des données. Commencez avec vos requêtes cibles et travaillez vers le modèle de données optimal.

Is this reasonable?

Je voudrais également créer une table plate supplémentaire avec toutes les données.

run_id | spectrum_id | data_id | <data table columns..> |

Je vais utiliser cette table comme source principale de toutes les requêtes. La raison est d'éviter de devoir faire des jointures. Les jointures sans indexation rendront votre système très inutilisable, et avoir des index sur des fichiers aussi volumineux sera tout aussi terrible.

La stratégie consiste à lancer une requête sur la table ci-dessus, à vider les résultats dans une table temporaire et à joindre la table temporaire aux tables de recherche de Run et Spectrum et à obtenir les données souhaitées.


Avez-vous analysé vos besoins en écriture par rapport à vos besoins en lecture? Il sera très tentant d’abandonner SQL et d’utiliser des mécanismes de stockage de données non standard. À mon avis, cela devrait être le dernier recours.

Pour accélérer les vitesses d’écriture, vous pouvez essayer la méthode Handler Socket. Percona, si je me souviens bien, empaquete Handler Socket dans son paquet d'installation. (pas de relation avec Percona!)

http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html

srini.venigalla
la source
33

La réponse courte est un oui qualifié: à mesure que le nombre de lignes augmente, le schéma précis, les types de données et les opérations que vous choisissez gagnent en importance.

La mesure dans laquelle vous normalisez vos données dépend des opérations que vous prévoyez d'effectuer sur les données stockées. Votre tableau de «points de données» en particulier semble poser problème - prévoyez-vous de comparer le nième point d'un spectre donné à celui d'un autre? Sinon, les stocker séparément pourrait être une erreur. Si vos points de données ne sont pas autonomes mais ont un sens uniquement dans le contexte de leurs spectres associés, vous n'avez pas besoin d'une clé primaire - une clé étrangère du spectre et une "nième" colonne (votre colonne "index"?) Suffiront .

Définissez les opérations inter et intra-spectre que vous devez effectuer, puis déterminez le moyen le moins coûteux de les réaliser. Si l’égalité est tout ce qui est nécessaire, elles peuvent être dénormalisées - éventuellement avec des métadonnées statistiques pré-calculées qui facilitent vos opérations. Si vous avez absolument besoin d'un accès in-SQL à des points de données individuels, veillez à réduire la taille de chaque ligne au nombre minimal de champs et au type de données le plus petit possible.

Le plus gros MySQL que j'ai jamais géré personnellement était d'environ 100 millions de lignes. A cette taille, vous souhaitez conserver vos lignes et donc vos champs de taille fixe. Cela permet à MySQL de calculer efficacement la position de toute ligne du tableau en multipliant par la taille fixe de chaque ligne (pensez à l'arithmétique de pointeur). Les détails exacts dépendent du moteur de stockage que vous prévoyez d'utiliser. Utilisez MyISAM si vous pouvez vous en tirer, son manque de fiabilité est compensé par sa rapidité et, dans votre cas, cela devrait suffire. Remplacez les champs de taille variable tels que VARCHAR par CHAR (n) et utilisez RTRIM () dans vos requêtes en lecture.

Une fois que vos rangées de tableau ont une largeur fixe, vous pouvez réduire le nombre d'octets en évaluant soigneusement les types de données entiers de MySQL (dont certains ne sont pas standard). Chaque économie d'un octet obtenue en convertissant un INT de 4 octets en un octet de 3 octets, MEDIUMINT vous permet d'économiser environ 1 Mo par million de lignes, ce qui signifie moins d'E / S de disque et une mise en cache plus efficace. Utilisez les types de données les plus petits possibles . Évaluez avec soin les types à virgule flottante et voyez si vous pouvez remplacer les DOUBLES de 8 octets par des FLOAT de 4 octets ou même des NUMERIQUES en virgule fixe de moins de 8 octets . Faites des tests pour vous assurer que quoi que vous choisissiez ne vous morde pas plus tard.

En fonction des propriétés attendues de votre ensemble de données et des opérations requises, des encodages plus inhabituels de vos valeurs (motifs / répétitions attendus pouvant être encodés sous forme d'index dans un ensemble de valeurs peuvent être économisés), des données brutes pouvant contribuer de manière significative à métadonnées et être rejetées, etc.) - bien que des optimisations exotiques, non intuitives et destructives ne valent la peine que lorsque toutes les autres options ont été essayées.

Plus important encore, peu importe ce que vous finissez par faire, ne supposez pas que vous avez sélectionné le schéma parfait, puis commencez aveuglément à vider des dizaines de millions d'enregistrements. Les bonnes conceptions prennent du temps à évoluer. Créez un ensemble volumineux mais gérable (par exemple 1-5%) de données de test et vérifiez l'exactitude et les performances de votre schéma. Observez le fonctionnement des différentes opérations (http://dev.mysql.com/doc/refman/5.0/en/using-explain.html) et veillez à équilibrer votre schéma pour favoriser les opérations les plus fréquentes.

Ai-je dit court? Oups. Quoi qu'il en soit, bonne chance!

Ryan Flynn
la source
23

Il semblerait que la seule raison pour détruire les données de points de données hors XML (par opposition aux métadonnées telles que l'heure et le type d'analyse) et dans un formulaire de base de données est lorsque vous analysez les spectres sur des tableaux - c.-à-d. fonctionne avec une certaine signature. Vous êtes le seul à connaître votre domaine de problème pour le moment, mais cela pourrait ressembler à stocker de la musique échantillonnée à 96 kHz avec un échantillon par ligne. Je ne suis pas sûr que la taille soit le problème plus que la manière dont les données sont utilisées. Interroger des données équivaudrait à demander l'amplitude relative deux minutes après le début de la chanson pour toutes les chansons de The Beatles. Si vous connaissez le type d’analyses pouvant être effectuées, il est tout à fait possible que leur exécution sur les signaux et leur stockage dans les métadonnées relatives à la course aient plus de sens.

Je ne suis pas sûr non plus que vos données sources soient rares. Il est tout à fait possible qu'un spectre de la base de données n'inclue que des entrées non nulles, tandis que le code XML d'origine n'inclut aucune entrée. Le nombre total de lignes peut donc être bien inférieur à celui des données source.

Donc, comme beaucoup de questions, avant de poser des questions sur le traitement de votre modèle par MySQL, il est probablement plus approprié de revenir en arrière et de regarder comment le modèle va être utilisé.


Après avoir examiné les mises à jour de vos questions, je pense qu'un modèle dans lequel les données binaires sont stockées sous la forme d'un BLOB ou simplement un pointeur sur le fichier est suffisant et que vous modifiez votre modèle pour stocker des données sur les pics significatifs qui ont été identifiés lors de la première utilisation des données. lis.

Cade Roux
la source
18

J'exécute un service d'analyse Web avec environ 50 serveurs de base de données, chacun contenant de nombreuses tables de plus de 100 millions de lignes, et plusieurs d'entre elles ayant tendance à dépasser le milliard de lignes, parfois jusqu'à deux milliards (sur chaque serveur).

La performance ici est bien. Ce sont des données très normalisées. Cependant, ma principale préoccupation en lisant ceci est que vous dépasserez largement la barre des 4,2 milliards de lignes pour ces tables (peut-être pas "tourne" mais probablement les deux autres), ce qui signifie que vous devrez utiliser BIGINT au lieu de INT pour les clés primaires / étrangères.

Les performances de MySQL avec les champs BIGINT dans une colonne indexée sont ridiculement horribles comparées à INT. J'ai fait l'erreur de le faire une fois avec une table dont la taille, à mon avis, pourrait dépasser cette taille. Une fois atteint quelques centaines de millions de lignes, les performances étaient tout simplement catastrophiques. Je n'ai pas de chiffres bruts, mais quand je dis mal, je veux dire mauvais Windows ME.

Cette colonne était la clé primaire. Nous l'avons reconverti pour être juste un INT et presto magico, la performance était encore bonne.

À l’époque, tous nos serveurs utilisaient Debian 5 et MySQL 5.0. Nous avons depuis mis à jour Debian 6 et Percona MySQL 5.5, donc les choses se sont peut-être améliorées depuis. Mais sur la base de mon expérience ici, non, je ne pense pas que cela fonctionnera très bien.

Sean
la source
17

Que cela fonctionne ou non, vous rencontrez toujours le même problème avec un seul support de stockage monolithique: les disques sont lents. À 100 Mo / s (assez bon pour les médias en rotation), il suffit de 3 heures pour lire une table de 1 To; en supposant qu'aucune analyse ou recherche ou autre retard ne vous ralentisse.

C'est pourquoi presque chaque installation "big data" utilise une sorte de magasin de données distribué. Vous pouvez dépenser 8 fois plus d'argent pour construire un ordinateur vraiment génial pour exécuter votre base de données, mais si vous avez beaucoup de données numérisables en parallèle, il est presque toujours préférable de répartir la charge sur les 8 ordinateurs les moins chers.

Des projets tels que Hadoop ont été construits spécifiquement pour des objectifs comme celui-ci. Vous construisez une grappe d'ordinateurs peu coûteux, répartissez les données sur tous les ordinateurs et les interrogez en parallèle. Ce n’est qu’une solution parmi une demi-douzaine de solutions, toutes construites autour de cette même idée, mais c’est une solution très populaire.

tylerl
la source
13

Hm ... Je vois deux raisons pour lesquelles vous choisiriez ce type de structure de données:

  • vous devez vraiment faire n'importe quel point de donnée par rapport à toutes les requêtes de point de donnée
  • vous avez l'intention d'effectuer toute votre logique en SQL

Maintenant, je suggérerais de jeter un regard long sur vos besoins et de vérifier qu’au moins une des hypothèses ci-dessus est vraie. Si ni l'un ni l'autre n'est vrai, vous ralentissez simplement les choses. Pour ce type de jeu de données, je suggérerais tout d'abord de déterminer comment l'accès aux données, le type de précision dont vous aurez besoin, etc. - puis de concevoir votre base de données en fonction de celles-ci.

PS: N'oubliez pas que vous aurez besoin d'au moins 36 + 5 octets par point de données. Par conséquent, avec 200 points de données, vous devriez obtenir au moins 8,2 To d'espace requis.

PPS: Vous n'avez pas besoin de la idcolonne dans la datapointstable, un PRIMARY KEY (spectrum_id, index)suffise probablement (attention, ce indexpeut être un mot réservé)


la source
12

MODIFIER:

NE PAS FAIRE CELA DANS MYSQL AVEC DES DONNÉES STOCKÉES SUR UN SEUL DISQUE. La simple lecture de cette quantité de données à partir d'un seul support prendra des heures. Vous avez besoin de SCALE OUT, PAS UP.

Et vous devez dénormaliser vos données si vous souhaitez effectuer une analyse efficace des données. Vous ne concevez pas un système en ligne ici. Vous voulez réduire les chiffres, concevoir en conséquence.

Réponse originale sous la ligne.


La réponse varie en fonction de vos requêtes. MySQL n'est peut-être pas le meilleur outil pour ce travail. Vous voudrez peut-être chercher une solution que vous pouvez utiliser "en dehors" et non "en haut". Si vous êtes prêt à faire un effort, vous devriez peut-être chercher une solution de type Map Reduce telle que Hadoop.

Si vous souhaitez effectuer davantage de requêtes ponctuelles, la solution BigQuery de Google peut vous convenir. Présentation pertinente de Google I / O 2012: traiter les Big Data avec BigQuery

Ainsi, la solution dépendra du caractère ponctuel et de la prise en charge raisonnable des requêtes ad hoc.

mdolk
la source
9

Personne n'a mentionné, donc ma suggestion. Jetez un coup d'œil aux solutions MySQL massivement partagées . Voir, par exemple, cette présentation très appréciée de tumblr .

Le concept est:

  • Au lieu d'une base de données extra-large
  • Utilisez beaucoup de petits fichiers contenant des parties des données d'origine

Ainsi, vous pouvez évoluer horizontalement au lieu d'essayer d'améliorer les performances verticales. BigTable et GFS de Google utilisent également des nœuds bon marché et évolutifs horizontalement pour stocker et interroger des pétaoctets de données.

Cependant, il y aura des problèmes si vous devez exécuter des requêtes sur différents fragments.


Si vous êtes intéressé, j'ai récemment fait une demande de partage du monde entier. On en parle ici dans un article de blog. J'ai utilisé RavenDB et C # mais les détails ne sont pas pertinents et l'idée est la même.

oleksii
la source
7

Sur quel type de machine les données vont-elles être stockées? Est-ce un périphérique de stockage partagé?

Le facteur ultime qui déterminera le temps de votre requête sera vos disques durs. Les bases de données et leurs optimiseurs de requêtes sont conçus pour réduire autant que possible le nombre d'E / S de disque. Étant donné que vous n'avez que 3 tables, cela se fera de manière assez fiable.

Les vitesses de lecture / écriture d'un disque dur vont être 200 à 300 fois inférieures à la vitesse de la mémoire. Recherchez les disques durs avec une latence très rapide et des vitesses de lecture et d’écriture rapides. Si toutes ces données se trouvent sur un disque de 2 To, vous allez probablement attendre longtemps pour que les requêtes se terminent. La latence du disque dur est d'environ 10-15 millisecondes alors que la latence de la mémoire est inférieure à 10 nanosecondes. La latence du disque dur peut être 1000-2000x plus lente que la latence de la mémoire. Le mouvement du bras mécanique sur le disque dur est la chose la plus lente dans tout ce système.

Combien de RAM avez-vous? 16 GB? Disons que cela vous permet de conserver 32 enregistrements. Vous avez 16000 fichiers. Si vous souhaitez balayer linéairement tous les points de données, vous pouvez facilement vous retrouver avec 5 à 10 secondes de temps de recherche seul. Alors facteur dans le taux de transfert 50mb / s? Environ 7 heures. De plus, toutes les données sauvegardées temporairement devront être stockées sur le disque dur pour laisser la place à de nouvelles données en cours de lecture.

Si vous utilisez un périphérique de stockage partagé utilisé activement par d'autres utilisateurs ... votre meilleur choix sera de tout gérer la nuit.

Réduire le nombre de requêtes imbriquées aide également bien. Les requêtes imbriquées génèrent des tables temporaires qui écraseront encore plus votre disque dur. J'espère que vous avez BEAUCOUP d'espace libre sur votre disque dur.

L'optimisation de la requête ne peut examiner qu'une requête à la fois. Les instructions select imbriquées ne peuvent donc pas être optimisées. CEPENDANT, si vous savez qu'une requête imbriquée spécifique va renvoyer un petit ensemble de données, conservez-le. L'optimisation de la requête utilise des histogrammes et des hypothèses approximatives. Si vous savez quelque chose à propos des données et de la requête, poursuivez l'opération.

Plus vous en saurez sur la manière dont vos données sont stockées sur le disque, plus vous pourrez écrire rapidement vos requêtes. Si tout a été stocké de manière séquentielle sur la clé primaire, il peut être intéressant de trier les clés primaires renvoyées par une requête imbriquée. En outre, si vous pouvez réduire l'ensemble des jeux de données que vous devez analyser au préalable, faites-le. En fonction de votre système, il faut environ 1 seconde de transfert de données par fichier.

Si vous envisagez de modifier les valeurs de nom (les varchars), je les changerais en un type de données de taille maximale, cela éviterait la fragmentation et le compromis ne serait que de quelques octets de mémoire supplémentaires. Peut-être un NVARCHAR avec 100 maximum.

En ce qui concerne les commentaires sur la dénormalisation de la table. Je pense qu'il serait peut-être préférable de simplement stocker les points de données dans des groupes plus importants (peut-être sous forme de spectres), puis de procéder à l'analyse des données en python ou dans un langage qui interagit avec la base de données. Sauf si vous êtes un assistant SQL.

JustinDanielson
la source
3
Vous insistez sur l’énorme différence entre latence disque et disque dur, mais vos chiffres sont divisés par 1 000. Si les disques durs ont une latence d’environ 10 ms et la mémoire 10ns, les latences ne diffèrent pas d’un facteur 1 000 mais d’un facteur de 1 000 000!
spectre256
6

Pour moi, cela ressemble à un scénario d'utilisation dans lequel vous voulez quelque chose comme un "magasin de colonnes relationnel" comme décrit ici .

Je ne comprends peut-être pas bien la conception, mais si vous traitez principalement avec une grande collection de tableaux, leur stockage dans des tableaux orientés ligne typiques signifie que chaque élément est similaire à une tranche. Si vous souhaitez examiner les tranches de manière classique, cela a du sens, mais cela pourrait être moins efficace si vous regardez vraiment des colonnes entières à la fois.

Lors de la récupération des tableaux, vous pouvez non seulement ne pas avoir besoin de la joindre à une autre table résultant de votre normalisation, mais vous pouvez également récupérer la série sous la forme d'un tableau plutôt que d'un hachage.

Je peux vraiment mal comprendre le problème, et je ne suggère même pas une solution spécifique.

Voici un autre exposé qui pourrait être pertinent, même s'il ne s'agit pas vraiment d'une solution actuelle ou déployable.

RandallZ
la source
6

Je vous recommande d'essayer de partitionner votre table. Nous avons plus de 80 millions de lignes dans une seule table (données boursières) et n'avons aucun problème à y accéder rapidement.

Selon la manière dont vous envisagez de rechercher vos données, vous devez concevoir vos partitions. Dans notre cas, par date fonctionne bien car nous demandons des dates spécifiques.

http://dev.mysql.com/doc/refman/5.1/en/partitioning-limitations.html

http://www.slideshare.net/datacharmer/mysql-partitions-tutorial

utilisateur9866
la source
5

Oui mais...

J'ai travaillé avec des tables qui avaient 2 milliards de lignes. Cependant, seules les requêtes utilisant PK devaient être rapides.

Plus important encore, le matériel disposait de suffisamment de RAM pour stocker des tables entières en mémoire. Lorsque cela est devenu un problème (maximum à 96 Go à ce moment-là), nous avons opté pour le partitionnement vertical, en gardant la taille de la table définie sur chaque machine suffisamment petite pour tenir en mémoire. De plus, les machines étaient connectées via une fibre optique de 10 Gb, de sorte que le débit du réseau n'était pas un problème.

BTW. votre schéma ressemble à quelque chose qui pourrait s’intégrer à la solution NoSQL, en utilisant run_idcomme clé de hachage pour les spectres et spectrum_idcomme clé de hachage pour les points de données.

vartec
la source
4

J'ai écrit sur ce sujet sur mon blog: http://www.tocker.ca/2013/10/24/improving-the-performance-of-large-tables-in-MySQL.html

Pour répéter certains des points clés:

  • Les arbres B se dégradent lorsqu'ils grossissent et ne rentrent pas dans la mémoire (MySQL n'est pas le seul ici).
  • InnoDB possède certaines fonctionnalités permettant de maintenir certaines performances (mise en mémoire tampon de changement; auparavant appelée «insert buffer»).
  • Le partitionnement peut aussi aider.

Dans les commentaires de mon article Tim Callaghan lié à ceci: http://www.tokutek.com/resources/benchmark-results/benchmarks-vs-innodb-hdds/#iiBench

Ce qui montre l'insertion de 1 milliard de lignes en utilisant le repère iibench.

Morgan Tocker
la source