web-dev-qa-db-fra.com

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

Je prévois de stocker des analyses à partir 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 l'ordre de grandeur approximatif: les requêtes prendront-elles 5 jours ou 5 millisecondes?

Format d'entrée

Chaque fichier d'entrée contient un seul passage du spectromètre; chaque exécution est composée d'un ensemble d'analyses et chaque analyse possède un tableau ordonné de points de données. Il y a un peu de métadonnées, mais la majeure partie du fichier est constituée de tableaux d'entiers ou de flottants 32 ou 64 bits.

Système hôte

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

Il existe d'autres services exécutés sur le serveur en utilisant un temps processeur négligeable.

Statistiques de fichier

 | ------------------ + -------------- | 
 | nombre de fichiers | ~ 16 000 | 
 | taille totale | 1,3 TiB | 
 | taille min | 0 octet | 
 | taille max | 12 GiB | 
 | Moyenne | 800 Mio | 
 | Médiane | 500 Mio | 
 | Total de points de données | ~ 200 milliards | 
 | ------------------ + -------------- | 

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

Schéma proposé

Je prévois de faire les choses "correctement" (c'est-à-dire normaliser les données comme un fou) et aurait donc une table runs, une table spectra avec une clé étrangère vers runs et une table datapoints avec une clé étrangère vers spectra.

La question des 200 milliards de points de données

Je vais analyser sur plusieurs spectres et peut-être même sur plusieurs exécutions, ce qui entraînera des requêtes qui pourraient 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'essaie 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 d'analyse proviendront de fichiers au format --- --- (mzML basé sur XML. La viande de ce format est dans le <binaryDataArrayList> éléments où les données sont stockées. Chaque scan produit> = 2 <binaryDataArray> éléments qui, pris ensemble, forment un tableau à deux dimensions (ou plus) de la forme [[123.456, 234.567, ...], ...].

Ces données sont à écriture unique, donc les performances de mise à jour et la sécurité des transactions ne sont pas des problèmes.

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

runs table

 | nom de la colonne | tapez | 
 | ------------- + ------------- | 
 | id | CLÉ PRIMAIRE | 
 | start_time | TIMESTAMP | 
 | nom | VARCHAR | 
 | ------------- + ------------- | 

spectra table

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

datapoints table

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

Est-ce raisonnable?


Donc, comme vous avez pu en déduire, je suis le programmeur, pas le biologiste du laboratoire, donc je ne connais pas aussi bien la science que les scientifiques.

Voici un tracé d'un spectre unique (scan) du type de données que je traiterai:

Viewer screenshot

Le but du logiciel est de déterminer où et comment les pics sont significatifs. Nous utilisons un progiciel propriétaire pour comprendre cela maintenant, mais nous voulons écrire notre propre programme d'analyse (en R) afin que nous sachions ce qui se passe sous les feuilles. Comme vous pouvez le voir, la grande majorité des données ne sont pas intéressantes, mais nous ne voulons pas jeter de données potentiellement utiles que notre algorithme a manquées. Une fois que nous avons une liste des pics probables dont nous sommes satisfaits, le reste du pipeline utilisera cette liste de pics plutôt que la liste brute des points de données. Je suppose qu'il serait suffisant de stocker les points de données bruts comme un gros blob, afin qu'ils puissent être réanalysés si nécessaire, mais ne gardez que les pics comme entrées de base de données distinctes. Dans ce cas, il n'y aurait que quelques dizaines de pics par spectre, donc les choses folles à l'échelle ne devraient pas être autant un problème.

285
haxney

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 exagéré. Cela ressemble presque à l'approche de stockage d'une bibliothèque d'images en stockant chaque pixel en tant qu'enregistrement distinct 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 incorrect la plupart du temps. Il existe généralement une meilleure façon de résoudre le problème. Bien qu'il ne soit pas intrinsèquement mauvais 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, sont les mieux adaptées pour stocker des données relationnelles. Les données binaires ne sont pas relationnelles. Il 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 d'un milliard 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! Créez simplement un répertoire et une structure de dénomination de fichiers pour vos fichiers binaires, stockez-les dans votre base de données MySQL avec toutes les autres données qui peuvent générer de la valeur grâce à l'interrogation.

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 des spectres) et à utiliser MySQL pour les exécutions (ou peut-être à placer les exécutions dans la même base de données que les autres).

117
Krystian Cybulski

J'ai déjà travaillé avec une très grande base de données MySQL (Terabyte +). La plus grande table que nous avions comptait 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 lourd cependant. (Si vous voulez une disponibilité de six sigma avec un téraoctet de données, n'utilisez pas MySQL. Nous étions une startup qui n'avait pas de DBA et des fonds limités.)

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

Nous avions de nombreuses tables dans la plage de 10 à 100 millions de lignes. Toute jointure importante aux tables prenait 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 aux plages d'id. De cette façon, nous traiterions les données de 10 à 100 000 lignes à la fois (joindre contre les identifiants 1-100 000 puis 100 001-200 000, etc.). C'était beaucoup plus rapide que de se joindre à l'ensemble de la table.

L'utilisation d'index sur de très grandes tables 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: MySQL va d'abord à un index et en extrait les valeurs de clé primaire qu'il doit trouver, puis il fait une deuxième recherche sur l'index de clé primaire pour trouver où se trouvent ces valeurs.

Le net de ceci est que 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 d'index moins nombreux et plus simples. Et faire même des instructions select simples qui ne sont pas directement sur un index peut 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 grandes tables et faire des calculs et obtenir des réponses correctes.

Essayer de faire une analyse sur 200 milliards de lignes de données nécessiterait un matériel très haut de gamme et beaucoup de tenue de main et de patience. Garder simplement les données sauvegardées dans un format à partir duquel vous pouvez restaurer serait un travail important.

Je suis d'accord avec la réponse de srini.venigalla que normaliser les données comme un fou peut ne pas être 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 signifier que certaines de vos requêtes ne reviendraient jamais. La dénormalisation avec des clés simples et entières vous donnerait de meilleures chances de succès.

Tout ce que nous avions était InnoDB. Concernant MyISAM vs InnoDB: L'essentiel serait de ne pas mélanger les deux. Vous ne pouvez pas vraiment optimiser un serveur pour les deux en raison 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 avec certains problèmes de vitesse, mais il peut ne pas aider avec le travail DBA global qui doit être fait - ce qui peut être un tueur.

111
Kevin Bedell

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 forme normalisée et sous forme de vues matérialisées très adaptées à votre application. La clé de ce type d'applications n'est PAS d'écrire des requêtes ad hoc. La modélisation des requêtes est plus importante que la modélisation des données. Commencez par 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..> |

J'utiliserai ce tableau comme source principale de toutes les requêtes. La raison est d'éviter d'avoir à faire des jointures. Les jointures sans indexation rendront votre système très inutilisable, et avoir des index sur de tels fichiers énormes sera tout aussi terrible.

La stratégie consiste à interroger d'abord le tableau ci-dessus, à vider les résultats dans une table temporaire et à joindre la table temporaire avec les tables de recherche de Run et Spectrum et d'obtenir les données que vous souhaitez.


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

Pour accélérer les vitesses d'écriture, vous souhaiterez peut-être essayer la méthode Handler Socket. Percona, si je me souviens bien, empaquette Handler Socket dans son package d'installation. (aucun rapport avec Percona!)

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

70
srini.venigalla

La réponse courte est un oui qualifié - à mesure que le nombre de lignes augmente, le schéma, les types de données et les opérations que vous choisissez prennent de plus en plus d'importance.

Le degré de normalisation de vos données dépend des opérations que vous prévoyez d'effectuer sur les données stockées. Votre table de "points de données" en particulier semble problématique - prévoyez-vous de comparer le nième point d'un spectre donné avec le mois d'un autre? Sinon, les stocker séparément pourrait être une erreur. Si vos points de données ne sont pas autonomes mais n'ont de sens que dans le contexte de leurs spectres associés, vous n'avez pas besoin d'une CLÉ PRIMAIRE - une clé étrangère pour les spectres et une "nième" colonne (votre colonne "index"?) Suffiront .

Définissez les opérations inter- et intra-spectre que vous devez effectuer, puis trouvez le moyen le moins cher de les accomplir. 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 aident vos opérations. Si vous avez absolument besoin d'un accès en SQL à des points de données individuels, assurez-vous de réduire la taille de chaque ligne au nombre minimal de champs et au plus petit type de données possible.

Le plus grand MySQL que j'ai jamais géré personnellement était d'environ 100 millions de lignes. À cette taille, vous voulez garder vos lignes et donc vos champs de taille fixe - cela permet à MySQL de calculer efficacement la position de n'importe quelle ligne de la table en multipliant par la taille fixe de chaque ligne (pensez à l'arithmétique du pointeur) - bien que les détails exacts dépendent du moteur de stockage que vous prévoyez d'utiliser. Utilisez MyISAM si vous pouvez vous en sortir, ce qu'il manque de fiabilité, il compense en vitesse, et dans votre situation, cela devrait suffire. Remplacez les champs de taille variable tels que VARCHAR par CHAR (n) et utilisez RTRIM () dans vos requêtes de lecture.

Une fois que vos lignes de table sont de 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 que vous pouvez retirer en convertissant un INT de 4 octets en un MEDIUMINT de 3 octets vous permet d'économiser environ 1 Mo par million de lignes, ce qui signifie moins d'E/S disque et une mise en cache plus efficace. Utilisez les plus petits types de données possibles avec lesquels vous pouvez vous en sortir . Évaluez soigneusement les types à virgule flottante et voyez si vous pouvez remplacer les DOUBLE de 8 octets par des FLOAT de 4 octets ou même <8 octets NUMÉRIQUES à virgule fixe . Exécutez des tests pour vous assurer que tout ce que vous choisissez ne vous mordra pas plus tard.

En fonction des propriétés attendues de votre ensemble de données et des opérations requises, il peut y avoir d'autres économies dans des encodages plus inhabituels de vos valeurs (modèles/répétitions attendus qui peuvent être encodés sous forme d'index dans un ensemble de valeurs, données brutes qui ne peuvent que contribuer de manière significative à métadonnées et supprimées, etc.) - bien que les optimisations exotiques, non intuitives et destructrices ne valent 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 choisi le schéma parfait, puis commencez aveuglément à vider des dizaines de millions d'enregistrements. Les bons designs mettent du temps à évoluer. Créez un ensemble de données de test volumineux mais gérable (disons 1 à 5%) et vérifiez l'exactitude et les performances de votre schéma. Découvrez comment différentes opérations fonctionnent (http://dev.mysql.com/doc/refman/5.0/en/using-explain.html) et assurez-vous d'é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!

33
Ryan Flynn

Il semblerait que la seule raison de déchiqueter les données des points de données hors du XML (par opposition aux métadonnées comme l'heure et le type d'exécution) et dans un formulaire de base de données est lorsque vous analysez les spectres à travers les tableaux - c'est-à-dire peut-être en trouvant tous s'exécute avec une certaine signature. Vous seul connaissez votre domaine problématique en ce moment, mais cela pourrait s'apparenter à stocker de la musique échantillonnée à 96 kHz avec 1 échantillon par ligne. Je ne suis pas sûr que la taille soit plus un problème que la façon dont les données sont utilisées. Interroger les données équivaudrait à demander l'amplitude relative de 2 minutes dans la chanson pour toutes les chansons des Beatles. Si vous connaissez le type d'analyses qui pourraient être effectuées, il est tout à fait possible que les effectuer sur les signaux et les stocker dans les métadonnées relatives à l'analyse ait plus de sens.

Je ne sais pas non plus si vos données source sont rares. Il est tout à fait possible qu'un spectre dans la base de données ne comprenne que des entrées non nulles tandis que le XML d'origine inclut des entrées nulles, et donc votre nombre total de lignes pourrait être beaucoup moins que dans les données source.

Donc, comme beaucoup de questions, avant de demander à MySQL de gérer votre modèle, prendre du recul et regarder le modèle et comment il va être utilisé est probablement plus approprié que de se soucier des performances pour le moment.


Après avoir examiné les mises à jour de vos questions, je pense qu'un modèle où les données binaires sont stockées en tant que BLOB ou juste un pointeur vers le fichier est suffisant et travaille sur la modification de votre modèle pour stocker des données sur les pics significatifs qui ont été identifiés lorsque les données sont d'abord lis.

23
Cade Roux

Je gère un service d'analyse Web avec environ 50 serveurs de bases de données, chacun contenant de nombreuses tables de plus de 100 millions de lignes, et plusieurs qui ont tendance à dépasser le milliard de lignes, parfois jusqu'à deux milliards (sur chaque serveur).

La performance ici est bonne. Ce sont des données très normalisées. Cependant - ma principale préoccupation en lisant ceci est que vous serez bien au-dessus de la barre des 4,2 milliards de lignes pour ces tables (peut-être pas "s'exécute" 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 par rapport à INT. J'ai fait l'erreur de le faire une fois avec une table que je pensais pouvoir dépasser cette taille, et une fois qu'elle a atteint quelques centaines de millions de lignes, les performances étaient tout simplement épouvantables. Je n'ai pas de chiffres bruts mais quand je dis mauvais, je veux dire que Windows ME est mauvais.

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

Tous nos serveurs étaient à l'époque sur Debian 5 et avec MySQL 5.0. Nous avons depuis mis à niveau vers Debian 6 et Percona MySQL 5.5, donc les choses peuvent s'être améliorées depuis lors. Mais d'après mon expérience ici, non, je ne pense pas que cela fonctionnera très bien.

18
Sean

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

C'est pourquoi presque toutes les installations de "big data" utilisent une sorte de magasin de données distribuées. Vous pouvez dépenser 8 fois plus d'argent pour construire un ordinateur super incroyable pour exécuter votre base de données, mais si vous avez beaucoup de données qui peuvent être analysées en parallèle, il est presque toujours préférable de répartir la charge sur les 8 ordinateurs les moins chers.

Des projets comme hadoop ont été construits spécifiquement pour des objectifs comme celui-ci. Vous construisez un cluster de tout un tas d'ordinateurs peu coûteux, répartissez les données sur chacun d'entre eux et interrogez-les en parallèle. Ce n'est qu'une parmi une demi-douzaine de solutions toutes construites autour de cette même idée, mais elle est très populaire.

18
tylerl

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ées par rapport à toutes les requêtes de points de données
  • vous avez l'intention d'exécuter toute votre logique en SQL

Maintenant, je suggérerais de regarder attentivement vos exigences et de vérifier qu'au moins une des hypothèses ci-dessus est vraie. Si aucun des deux n'est vrai, vous ralentissez simplement les choses. Pour ce type de jeu de données, je suggérerais d'abord de savoir comment les données devraient être accessibles, de quel type de précision vous aurez besoin, etc. - puis de concevoir votre base de données autour de celles-ci.

P.S .: Gardez à l'esprit que vous aurez besoin d'au moins 36 + 5 octets par point de données, donc avec 200B points de données qui devraient vous donner au moins 8,2 TB espace requis).

PPS: vous n'avez pas besoin de la colonne id dans la table datapoints, une PRIMARY KEY (spectrum_id, index) suffit probablement (sachez simplement que index peut être un mot réservé )

13
Tassos Bassoukos

ÉDITER:

NE PAS FAIRE CECI EN MYSQL AVEC DES DONNÉES STOCKÉES SUR UN SEUL DISQUE. La lecture de cette quantité de données à partir d'un seul support prendra des heures. Vous devez ÉVOLUER, PAS HAUT.

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

Réponse originale sous la ligne.


La réponse variera 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 mettre à l'échelle "et non" à la hausse ". Si vous êtes prêt à faire des efforts, vous devriez peut-être chercher une solution Map Reduce telle que Hadoop.

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

Ainsi, la solution dépendra de la nature de cette opération ponctuelle et de la prise en charge raisonnable des requêtes ad hoc.

12
mdolk

Personne n'a mentionné, d'où ma suggestion. Jetez un œil aux solutions MySQL massivement partagées. Par exemple, voyez cette très appréciée présentation tumblr .

Le concept est:

  • Au lieu d'une base de données extra large
  • Utilisez de nombreux petits 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 évolutifs horizontalement bon marché 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 quelqu'un est intéressé, j'ai fait une application de partage de bonjour il y a quelque temps. Il est discuté 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.
9
oleksii

Sur quel type de machine les données seront-elles stockées? S'agit-il d'un périphérique de stockage partagé?

Le facteur ultime qui dictera 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 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 plus lentes que les vitesses de 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 lecteur 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 tandis 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 de tout ce système.

Combien RAM avez-vous? 16 Go? Disons que cela vous permet de conserver 32 enregistrements. Vous avez 16000 fichiers. Si vous allez scanner linéairement tous les points de données, vous pourriez facilement vous retrouver avec 5 à 10 secondes en temps de recherche seul. Tenez compte ensuite du taux de transfert de 50 Mo/s? Environ 7 heures. De plus, toutes les données enregistrées temporairement devront être stockées sur le disque dur pour faire de la place pour la lecture de nouvelles données.

Si vous utilisez un périphérique de stockage partagé qui est activement utilisé par d'autres utilisateurs ... votre meilleur pari va tout faire fonctionner la nuit.

Réduire le nombre de requêtes imbriquées est également utile. Les requêtes imbriquées aboutissent à des tables temporaires qui vont encore plus écraser votre disque dur. J'espère que vous avez BEAUCOUP d'espace libre sur votre disque dur.

L'optimisation des requêtes ne peut regarder qu'une seule requête à la fois. Les instructions select imbriquées ne peuvent donc pas être optimisées. TOUTEFOIS, si vous savez qu'une requête imbriquée spécifique va entraîner le renvoi d'un petit ensemble de données, conservez-le. L'optimisation des requêtes utilise des histogrammes et des hypothèses approximatives, si vous savez quelque chose sur les données et la requête, allez-y et faites-le.

Plus vous en saurez sur la façon dont vos données sont stockées sur disque, plus vite vous pourrez écrire vos requêtes. Si tout a été stocké séquentiellement sur la clé primaire, il peut être avantageux de trier les clés primaires renvoyées par une requête imbriquée. De plus, si vous pouvez réduire l'ensemble des ensembles de données que vous devez analyser au préalable, faites-le. Selon votre système, vous regardez environ 1 seconde de transfert de données par fichier.

Si vous allez modifier les valeurs de nom (les varchars), je le changerais en un type de données avec une taille maximale, cela empêchera la fragmentation et le compromis n'est 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 du tableau. Je pense qu'il 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 d'analyser les données en python ou dans un langage qui interagit avec la base de données. À moins que vous ne soyez un SQL- Sorcier.

7
JustinDanielson

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

Je peux mal comprendre la conception, mais si vous avez principalement affaire à une grande collection de tableaux, les stocker dans des tables orientées ligne signifie que chaque élément est similaire à une tranche. Si vous êtes intéressé à regarder les tranches d'une manière typique, 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, non seulement vous pourriez ne pas avoir besoin de le joindre à une autre table résultant de votre normalisation, mais vous pouvez récupérer la série sous forme de tableau plutôt que de 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 peut être pertinent, même s'il ne s'agit pas vraiment d'une solution actuelle ou déployable.

6
RandallZ

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 façon dont vous avez l'intention de rechercher vos données, vous devez concevoir vos partitions. Dans notre cas, la date fonctionne bien car nous recherchons des dates spécifiques.

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

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

6
user9866

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 avait suffisamment de RAM pour tenir des tables entières en mémoire. Lorsque cela est devenu un problème (maxi à 96 Go à l'époque), j'ai opté pour le partitionnement vertical, en gardant la taille de la table définie sur chaque la machine était suffisamment petite pour rester en mémoire. De plus, les machines étaient connectées via une fibre de 10 Go, donc le débit du réseau n'était pas vraiment un problème.

BTW. votre schéma ressemble à quelque chose, qui pourrait s'intégrer dans la solution NoSQL, en utilisant run_id comme clé de hachage pour les spectres et spectrum_id comme clé de hachage pour les points de données.

5
vartec

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 à mesure qu'ils grossissent et ne tiennent pas en mémoire (MySQL n'est pas le seul ici).
  • InnoDB a quelques fonctionnalités pour aider à maintenir certaines performances (changer la mise en mémoire tampon; auparavant appelé "insérer une mémoire tampon").
  • Le partitionnement peut également 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 à l'aide du benchmark iibench.

4
Morgan Tocker