MySQL può ragionevolmente eseguire query su miliardi di righe?


283

Sto programmando di archiviare scansioni da uno spettrometro di massa in un database MySQL e vorrei sapere se archiviare e analizzare questa quantità di dati è fattibile da remoto. So che le prestazioni variano notevolmente a seconda dell'ambiente, ma sto cercando l'ordine approssimativo di grandezza: le query impiegheranno 5 giorni o 5 millisecondi?

Formato di input

Ogni file di input contiene una singola corsa dello spettrometro; ogni esecuzione è composta da una serie di scansioni e ogni scansione ha una matrice ordinata di punti dati. Ci sono un po 'di metadati, ma la maggior parte del file è composta da array o float a 32 o 64 bit.

Sistema host

| ---------------- + ------------------------------- |
| OS | Windows 2008 a 64 bit |
| Versione MySQL | 5.5.24 (x86_64) |
| CPU | 2x Xeon E5420 (8 core in totale) |
| RAM | 8GB |
| File system SSD | 500 GiB |
| RAID HDD | 12 TiB |
| ---------------- + ------------------------------- |

Esistono altri servizi in esecuzione sul server che utilizzano un tempo del processore trascurabile.

Statistiche dei file

| ------------------ + -------------- |
| numero di file | ~ 16.000 |
| dimensione totale | 1.3 TiB |
| dimensione minima | 0 byte |
| dimensione massima | 12 GiB |
| media | 800 MiB |
| mediana | 500 MiB |
| punti dati totali | ~ 200 miliardi |
| ------------------ + -------------- |

Il numero totale di punti dati è una stima molto approssimativa.

Schema proposto

Sto programmando di fare le cose "giuste" (cioè normalizzare i dati come un matto) e quindi avremmo una runstabella, una spectratabella con una chiave esterna a runse una datapointstabella con una chiave esterna a spectra.

La domanda da 200 miliardi di punti dati

Analizzerò su più spettri e forse anche più sequenze, risultando in query che potrebbero toccare milioni di righe. Supponendo che indicizzo tutto correttamente (che è un argomento per un'altra domanda) e non sto cercando di mescolare centinaia di MiB attraverso la rete, è plausibile che MySQL sia in grado di gestirlo?

informazioni addizionali

I dati di scansione verranno dai file nel formato mzML basato su XML. La carne di questo formato è negli <binaryDataArrayList>elementi in cui sono memorizzati i dati. Ogni scansione produce> = 2 <binaryDataArray>elementi che, presi insieme, formano un array bidimensionale (o più) del modulo [[123.456, 234.567, ...], ...].

Questi dati vengono scritti una sola volta, quindi le prestazioni di aggiornamento e la sicurezza delle transazioni non rappresentano problemi.

Il mio piano ingenuo per uno schema di database è:

runs tavolo

| nome della colonna | digitare |
| ------------- + ------------- |
| id | CHIAVE PRIMARIA |
| start_time | TIMESTAMP |
| nome | VARCHAR |
| ------------- + ------------- |

spectra tavolo

| nome della colonna | digitare |
| ---------------- + ------------- |
| id | CHIAVE PRIMARIA |
| nome | VARCHAR |
| indice | INT |
| tipo_ spettro | INT |
| rappresentazione | INT |
| run_id | CHIAVE ESTERA |
| ---------------- + ------------- |

datapoints tavolo

| nome della colonna | digitare |
| ------------- + ------------- |
| id | CHIAVE PRIMARIA |
| spettro_id | CHIAVE ESTERA |
| mz | DOUBLE |
| num_counts | DOUBLE |
| indice | INT |
| ------------- + ------------- |

È ragionevole?


Quindi, come potresti aver potuto dedurre, io sono il programmatore, non il biologo in laboratorio, quindi non conosco la scienza tanto quanto i veri scienziati.

Ecco un diagramma di un singolo spettro (scansione) del tipo di dati con cui tratterò:

Schermata del visualizzatore

L'obiettivo del software è capire dove e quanto siano significativi i picchi. Usiamo un pacchetto software proprietario per capirlo ora, ma vogliamo scrivere il nostro programma di analisi (in R) in modo da sapere cosa diavolo sta succedendo sotto i fogli. Come puoi vedere, la stragrande maggioranza dei dati non è interessante, ma non vogliamo buttare via dati potenzialmente utili che il nostro algoritmo ha perso. Una volta che abbiamo un elenco di probabili picchi di cui siamo soddisfatti, il resto della pipeline utilizzerà tale elenco di picco anziché l'elenco non elaborato di punti dati. Suppongo che sarebbe sufficiente memorizzare i punti dati grezzi come un grande BLOB, in modo che possano essere rianalizzati se necessario, ma mantenere solo i picchi come voci distinte del database. In quel caso, ci sarebbero solo un paio di dozzine di picchi per spettro, quindi la roba del ridimensionamento pazzo non dovrebbe



8
Poiché si tratta di dati grezzi di spettrometro di massa polling A / D, sembra davvero stupido archiviarli nel database. Vorrei prendere i miei dati grezzi, scaricarli, elaborarli e archiviare i RISULTATI elaborati in un database. I risultati sarebbero (a) forme d'onda memorizzate una forma d'onda per riga, (b) altri dati associati a quelle forme d'onda come le curve di calibrazione e (c) righe dei risultati nel database. Ciò taglierebbe miliardi di file di gonfiore dal tuo disegno. Quando si desidera eseguire nuovamente un'analisi iniziale, è necessario modificare alcuni parametri, eseguire un'operazione di calcolo gigante e archiviare i nuovi risultati nel db.
Warren P

Risposte:


115

Non ho molta familiarità con le tue esigenze, ma forse memorizzare ogni punto di dati nel database è un po 'eccessivo. Sembra quasi l'approccio di memorizzare una libreria di immagini memorizzando ciascun pixel come record separato in un database relazionale.

Come regola generale, la memorizzazione dei dati binari nei database è errata per la maggior parte del tempo. Di solito esiste un modo migliore per risolvere il problema. Sebbene non sia intrinsecamente errato archiviare i dati binari nel database relazionale, spesso gli svantaggi superano i guadagni. I database relazionali, come suggerisce il nome, sono più adatti per la memorizzazione di dati relazionali. I dati binari non sono relazionali. Aggiunge dimensioni (spesso in modo significativo) ai database, può compromettere le prestazioni e può portare a domande sul mantenimento di istanze MySQL da miliardi di record. La buona notizia è che esistono database particolarmente adatti per la memorizzazione di dati binari. Uno di questi, sebbene non sempre prontamente evidente, è il tuo file system! Basta inventare una directory e una struttura di denominazione dei file per i tuoi file binari,

Un altro approccio potrebbe essere l'utilizzo di un sistema di archiviazione basato su documenti per i dati dei punti dati (e forse degli spettri) e l'utilizzo di MySQL per le esecuzioni (o forse l'inserimento delle esecuzioni nello stesso DB degli altri).


5
Perché è considerato sbagliato archiviare i dati binari in un database? (Chiedendo parzialmente perché sono curioso, ma anche perché posso pensare a un caso d'uso per questo.)

15
Se i dati binari non hanno alcun valore singolarmente, non devono essere archiviati come una riga univoca. Il pixel 500x325 su un'immagine è irrilevante.

1
Questo è un ottimo punto. Probabilmente dovremmo tenere in giro i file grezzi nel caso in cui dovessimo estrarre di nuovo le cose in seguito, ma l'analogia con la memorizzazione delle immagini è ottima. Non avremo mai bisogno di accedere a ciascun punto dati (a meno che non stiamo ripetendo l'estrazione del picco), quindi semplicemente archiviare le informazioni statistiche estratte sarebbe molto meglio.
haxney,

107

Una volta ho lavorato con un database MySQL molto grande (Terabyte +). Il tavolo più grande che avevamo era letteralmente oltre un miliardo di righe. Stava usando MySQL 5.0, quindi è possibile che le cose siano migliorate.

Ha funzionato. MySQL ha elaborato i dati correttamente per la maggior parte del tempo. Era estremamente ingombrante però. (Se si desidera la disponibilità a livello di sigma sei con un terabyte di dati, non usare MySQL. Eravamo una startup che non aveva DBA e fondi limitati.)

Il solo backup e archiviazione dei dati è stata una sfida. Ci sarebbero voluti giorni per ripristinare la tabella, se necessario.

Avevamo numerosi tavoli nell'intervallo di 10-100 milioni di righe. Eventuali join significativi ai tavoli richiedevano troppo tempo e richiederebbero un'eternità. Quindi abbiamo scritto le procedure memorizzate per "camminare" sulle tabelle ed elaborare i join rispetto a intervalli di "ID". In questo modo elaboreremmo i dati 10-100.000 righe alla volta (Unisci contro ID 1-100.000 quindi 100.001-200.000, ecc.). Ciò è stato significativamente più veloce rispetto a unirsi all'intero tavolo.

L'uso di indici su tabelle molto grandi che non sono basate sulla chiave primaria è anche molto più difficile. Mysql 5.0 memorizza gli indici in due parti: memorizza gli indici (diversi dall'indice primario) come indici ai valori della chiave primaria. Quindi le ricerche indicizzate vengono eseguite in due parti: prima MySQL passa a un indice e ne estrae i valori della chiave primaria che deve trovare, quindi esegue una seconda ricerca sull'indice della chiave primaria per trovare dove si trovano tali valori.

La rete di ciò è che per tabelle molto grandi (1-200 milioni più righe) l'indicizzazione rispetto alle tabelle è più restrittiva. Hai bisogno di meno indici, più semplici. E fare anche semplici istruzioni select che non sono direttamente su un indice potrebbe non tornare più. Dove le clausole devono colpire gli indici o dimenticarsene.

Ma tutto ciò detto, le cose hanno effettivamente funzionato. Siamo stati in grado di utilizzare MySQL con queste tabelle molto grandi e fare calcoli e ottenere risposte corrette.

Cercare di fare analisi su 200 miliardi di file di dati richiederebbe hardware di fascia alta e molta tenuta di mano e pazienza. Mantenere il backup dei dati in un formato che è possibile ripristinare sarebbe un lavoro significativo.

Sono d'accordo con la risposta di srini.venigalla che normalizzare i dati come un matto potrebbe non essere una buona idea qui. Fare join su più tabelle con così tanti dati ti aprirà al rischio di ordinamenti di file, il che potrebbe significare che alcune delle tue domande non tornerebbero mai più. La denormallizzazione con semplici tasti interi ti darebbe maggiori possibilità di successo.

Tutto ciò che avevamo era InnoDB. Per quanto riguarda MyISAM vs. InnoDB: la cosa principale sarebbe non mescolare i due. Non puoi davvero ottimizzare un server per entrambi a causa del modo in cui MySQL memorizza nella cache chiavi e altri dati. Scegli l'uno o l'altro per tutte le tabelle di un server, se puoi. MyISAM può aiutare con alcuni problemi di velocità, ma potrebbe non aiutare con il lavoro DBA complessivo che deve essere fatto, il che può essere un killer.


1
MySQL è migliorato molto nel settore degli indici (...) dalla 5.0. Sarebbe interessante vedere come si comporta ora.
Anello Ø

70

normalizzare i dati come un matto

In questo caso, normalizzare i dati come un matto potrebbe non essere la strategia giusta. Mantieni aperte le tue opzioni archiviando i dati sia in forma Normalizzata sia in forma di viste materializzate altamente adatte alla tua applicazione. La chiave in questo tipo di applicazioni NON sta scrivendo query ad hoc. La modellazione delle query è più importante della modellazione dei dati. Inizia con le tue query target e lavora verso il modello di dati ottimale.

Is this reasonable?

Vorrei anche creare una tabella piatta aggiuntiva con tutti i dati.

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

Userò questa tabella come fonte primaria di tutte le query. Il motivo è evitare di dover fare alcun join. Unire senza indicizzazione renderà il tuo sistema molto inutilizzabile e avere indici su file così grandi sarà ugualmente terribile.

La strategia è, prima interrogare sulla tabella sopra, scaricare i risultati in una tabella temporanea e unire la tabella temporanea con le tabelle di ricerca di Run e Spectrum e ottenere i dati desiderati.


Hai analizzato le tue esigenze di scrittura rispetto a quelle di lettura? Sarà molto allettante abbandonare SQL e passare a meccanismi di archiviazione dei dati non standard. A mio avviso, dovrebbe essere l'ultima risorsa.

Per accelerare la velocità di scrittura, potresti provare il metodo Handler Socket. Percona, se ricordo, i pacchetti Handler Socket nel loro pacchetto di installazione. (nessuna relazione con Percona!)

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


33

La risposta breve è un sì qualificato: poiché il numero di righe aumenta lo schema preciso, i tipi di dati e le operazioni scelti aumentano di importanza.

Quanto normalizzi i tuoi dati dipende dalle operazioni che prevedi di eseguire sui dati memorizzati. La tabella dei "punti dati", in particolare, sembra problematica: stai pensando di confrontare l'ennesimo punto di uno spettro dato con l'ennesimo di un altro? In caso contrario, memorizzarli separatamente potrebbe essere un errore. Se i tuoi punti dati non si distinguono da soli ma hanno senso solo nel contesto dei loro spettri associati non hai bisogno di una CHIAVE PRIMARIA - una chiave esterna per gli spettri e una colonna 'ennesima' (la tua colonna 'indice'?) Sarà sufficiente .

Definire le operazioni inter e intra-spettro che è necessario eseguire e quindi individuare il modo più economico per eseguirle. Se è necessaria l'uguaglianza, potrebbero essere denormalizzati, possibilmente con alcuni metadati statistici pre-calcolati che aiutano le tue operazioni. Se hai assolutamente bisogno dell'accesso in-SQL ai singoli punti dati assicurati di ridurre le dimensioni di ogni riga al numero minimo di campi e al tipo di dati più piccolo possibile.

Il più grande MySQL che abbia mai gestito personalmente era ~ 100 milioni di righe. A queste dimensioni vuoi mantenere le tue righe e quindi i tuoi campi a dimensione fissa - questo consente a MySQL di calcolare in modo efficiente la posizione di qualsiasi riga nella tabella moltiplicando per la dimensione fissa di ogni riga (pensa l'aritmetica del puntatore) - sebbene il i dettagli esatti dipendono dal motore di archiviazione che prevedi di utilizzare. Usa MyISAM se riesci a cavartela, ciò che manca di affidabilità compensa in velocità e nella tua situazione dovrebbe essere sufficiente. Sostituisci i campi di dimensioni variabili come VARCHAR con CHAR (n) e usa RTRIM () nelle tue query di lettura.

Una volta che le righe della tabella sono a larghezza fissa, è possibile ridurre il numero di byte valutando attentamente i tipi di dati interi di MySQL (alcuni dei quali non sono standard). Ogni risparmio di 1 byte che puoi ottenere convertendo un INT a 4 byte in un MEDIUMINT a 3 byte ti fa risparmiare ~ 1 MB per milione di righe, il che significa meno I / O su disco e cache più efficace. Utilizzare i tipi di dati più piccoli possibili con cui è possibile cavarsela . Valutare attentamente i tipi in virgola mobile e vedere se è possibile sostituire i DOUBLE a 8 byte con FLOAT a 4 byte o anche NUMERICI a virgola fissa <8 byte . Esegui i test per assicurarti che tutto ciò che scegli non ti morda in seguito.

A seconda delle proprietà attese del set di dati e delle operazioni richieste, potrebbero esserci ulteriori risparmi in codifiche più insolite dei valori (schemi / ripetizioni previsti che possono essere codificati come indice in un insieme di valori, dati grezzi che possono solo contribuire significativamente a metadati ed essere scartati, ecc.) - anche se ottimizzazioni esotiche, non intuitive e distruttive valgono la pena solo quando è stata provata ogni altra opzione.

Soprattutto, non importa quello che si finisce per fare, non dare per scontato di aver scelto lo schema perfetto e quindi iniziare ciecamente a scaricare 10 milioni di dischi. I buoni progetti richiedono tempo per evolversi. Crea un set di dati di test ampio ma gestibile (diciamo 1-5%) e verifica la correttezza e le prestazioni del tuo schema. Guarda come vengono eseguite le diverse operazioni (http://dev.mysql.com/doc/refman/5.0/en/using-explain.html) e assicurati di bilanciare lo schema per favorire le operazioni più frequenti.

Ho detto breve? Ops. Comunque buona fortuna!


23

Sembrerebbe che l'unica ragione per distruggere i dati dei punti di dati dall'XML (al contrario dei metadati come il tempo e il tipo di esecuzione) e in un modulo di database sia quando si analizzano gli spettri attraverso array - cioè forse si trova tutto funziona con una certa firma. Solo tu conosci il tuo dominio problematico in questo momento, ma questo potrebbe essere simile alla memorizzazione di musica campionata a 96kHz con 1 campione per riga. Non sono sicuro che la dimensione sia il problema più del modo in cui vengono utilizzati i dati. Interrogare attraverso i dati equivarrebbe a chiedere l'ampiezza relativa di 2 minuti nel brano in tutti i brani dei Beatles. Se conosci il tipo di analisi che potrebbero essere eseguite, è del tutto possibile che eseguirle sui segnali e memorizzare quelle nei metadati sulla corsa potrebbe avere più senso.

Inoltre, non sono sicuro che i tuoi dati di origine siano sparsi. È del tutto possibile che uno spettro nel database includa solo voci diverse da zero, mentre l'XML originale include voci zero e quindi il numero totale di righe potrebbe essere molto inferiore rispetto ai dati di origine.

Quindi, come molte domande, prima di chiedere a MySQL di gestire il tuo modello, fare un passo indietro e guardare il modello e come verrà utilizzato è probabilmente più appropriato che preoccuparsi delle prestazioni ancora.


Dopo aver esaminato gli aggiornamenti delle domande, penso che sia sufficiente un modello in cui i dati binari sono archiviati come BLOB o solo un puntatore al file e lavoro sulla modifica del modello per archiviare i dati sui picchi significativi che sono stati identificati quando i dati sono i primi leggere.


18

Gestisco un servizio di analisi web con circa 50 server di database, ognuno contenente molte tabelle con oltre 100 milioni di righe e diverse che tendono ad essere oltre un miliardo di righe, a volte fino a due miliardi (su ciascun server).

Le prestazioni qui vanno bene. Sono dati molto normalizzati. Tuttavia, la mia principale preoccupazione con la lettura di questo è che sarai ben oltre i 4,2 miliardi di righe per queste tabelle (forse non "corre" ma probabilmente le altre due), il che significa che dovrai usare BIGINT invece di INT per le chiavi primarie / esterne.

Le prestazioni di MySQL con i campi BIGINT in una colonna indicizzata sono ridicolmente orribili rispetto a INT. Ho commesso l'errore di farlo una volta con un tavolo che pensavo potesse crescere oltre queste dimensioni, e una volta che ha raggiunto alcune centinaia di milioni di righe, le prestazioni sono state semplicemente spaventose. Non ho numeri grezzi, ma quando dico male, intendo Windows ME male.

Questa colonna era la chiave primaria. Lo abbiamo convertito in un INT e presto magico, la performance è stata di nuovo buona.

Tutti i nostri server all'epoca erano su Debian 5 e con MySQL 5.0. Da allora abbiamo effettuato l'aggiornamento a Debian 6 e Percona MySQL 5.5, quindi da allora le cose potrebbero essere migliorate. Ma in base alla mia esperienza qui, no, non penso che funzionerà molto bene.


17

Indipendentemente dal fatto che funzioni o meno, incontrerai sempre lo stesso problema con un singolo supporto di archiviazione monolitico: i dischi sono lenti. A 100 MB / s (abbastanza buono per girare i media) ci vogliono 3 ore solo per leggere una tabella da 1 TB; ciò presuppone che nessuna analisi o ricerca o altri ritardi ti rallentino.

Questo è il motivo per cui quasi ogni installazione di "big data" utilizza una sorta di archivio di dati distribuiti. Puoi spendere 8 volte di più per costruire un computer super fantastico per eseguire il tuo DB, ma se hai molti dati che possono essere scansionati in parallelo, stai quasi sempre meglio distribuire il carico tra gli 8 computer più economici.

Progetti come hadoop sono stati realizzati appositamente per scopi come questo. Costruisci un cluster di un intero gruppo di computer economici, distribuisci i dati su tutti loro e li interroghi in parallelo. È solo una mezza dozzina di soluzioni tutte costruite attorno a questa stessa idea, ma è molto popolare.


13

Hm ... Vedo due motivi per cui scegliere questo tipo di struttura di dati:

  • hai davvero bisogno di fare qualsiasi datapoint contro qualsiasi query di datapoint
  • si intende eseguire tutta la logica in SQL

Ora, suggerirei di dare una lunga occhiata alle tue esigenze e verificare che almeno uno dei presupposti di cui sopra sia vero. Se nessuno dei due è vero, stai solo rendendo le cose più lente. Per questo tipo di set di dati, suggerirei prima di scoprire come si prevede di accedere ai dati, che tipo di accuratezza occorrerà, ecc., E quindi progettare il database attorno a quelli.

PS: tieni presente che avrai bisogno di almeno 36 + 5 byte per punto dati, quindi con 200B di punti dati che dovrebbero darti almeno 8,2 TB di spazio richiesto.

PPS: non hai bisogno della idcolonna nella datapointstabella, PRIMARY KEY (spectrum_id, index)probabilmente è sufficiente ( fai attenzione che indexpotrebbe essere una parola riservata)


12

MODIFICARE:

NON FARE QUESTO IN MYSQL CON I DATI MEMORIZZATI SU UN SOLO DISCO. La sola lettura di tale quantità di dati da un singolo supporto richiederà ore. È necessario SCALA, NON SU.

E devi denormalizzare i tuoi dati se vuoi fare un'analisi dei dati efficace. Non stai progettando un sistema online qui. Vuoi scricchiolare i numeri, progettare di conseguenza.

Risposta originale sotto la riga.


La risposta varierà a seconda delle tue domande, MySQL potrebbe non essere lo strumento migliore per questo lavoro. Potresti voler esaminare una soluzione che puoi scalare "out" e non "up". Se sei disposto a impegnarti, forse dovresti cercare una soluzione di riduzione della mappa come Hadoop.

Se vuoi fare più domande ad hoc, la soluzione BigQuery di Google potrebbe essere la soluzione giusta per te. Presentazione pertinente di Google I / O 2012: Crunching Big Data con BigQuery

Pertanto, la soluzione dipenderà dal fatto che si tratti di una cosa singola e se si desidera supportare ragionevolmente query ad hoc.


9

Nessuno ha menzionato, quindi il mio suggerimento. Dai un'occhiata alle soluzioni MySQL di grandi dimensioni . Ad esempio, vedi questa presentazione tumblr molto apprezzata .

Il concetto è:

  • Invece di un database extra large
  • Usa molti di quelli piccoli che contengono parti dei dati originali

In questo modo è possibile ridimensionare orizzontalmente, anziché cercare di migliorare le prestazioni verticali. Google BigTable e GFS utilizzano anche nodi economici scalabili in orizzontale per archiviare e interrogare petabyte di dati.

Tuttavia, ci saranno problemi se è necessario eseguire query su frammenti diversi.


Se qualcuno fosse interessato, ho fatto una domanda di sharding ciao-mondo qualche tempo fa. È discusso qui in un post sul blog. Ho usato RavenDB e C # ma i dettagli sono irrilevanti e l'idea è la stessa.


7

Su quale tipo di macchina verranno archiviati i dati? È un dispositivo di archiviazione condiviso?

L'ultimo fattore che determinerà il tempo di interrogazione sarà il tuo hard disk. I database e i relativi ottimizzatori di query sono progettati per ridurre il più possibile il numero di I / O del disco. Dato che hai solo 3 tabelle, questo sarà fatto in modo abbastanza affidabile.

Le velocità di lettura / scrittura di un hard disk saranno 200-300 volte più lente delle velocità di memoria. Cerca dischi rigidi con latenza molto elevata e velocità di lettura e scrittura elevate. Se tutti questi dati si trovano su un'unità da 2 TB, probabilmente stai aspettando da molto tempo che le query finiscano. La latenza del disco rigido è di ~ 10-15 millisecondi mentre la latenza della memoria è inferiore a 10nanosecondi. La latenza del disco rigido può essere 1000-2000x più lenta della latenza della memoria. Il movimento del braccio meccanico sull'hard disk è la cosa PIÙ LENTA in questo intero sistema.

Quanta RAM hai? 16 GB? Diciamo che ti permette di contenere 32 record. Hai 16000 file. Se stai per eseguire la scansione lineare di tutti i punti dati, potresti facilmente finire con 5-10 secondi nel solo tempo di ricerca. Quindi fattore nella velocità di trasferimento 50 mb / s? Circa 7 ore Inoltre, tutti i dati salvati temporaneamente dovranno essere archiviati sul disco rigido per fare spazio per la lettura di nuovi dati.

Se stai usando un dispositivo di archiviazione condiviso che viene attivamente utilizzato da altri utenti ... la tua scommessa migliore sarà eseguire tutto di notte.

Ridurre il numero di query nidificate aiuta anche bene. Le query nidificate producono tabelle temporanee che aumenteranno ulteriormente il tuo hard disk. Spero che tu abbia MOLTO spazio libero sul tuo hard disk.

L'ottimizzazione della query può guardare solo 1 query alla volta. Quindi le istruzioni select nidificate non possono essere ottimizzate. TUTTAVIA, se si conosce che una specifica query nidificata comporterà la restituzione di un piccolo set di dati, conservarlo. L'ottimizzazione della query utilizza istogrammi e ipotesi approssimative, se conosci qualcosa sui dati e sulla query, procedi e fallo.

Più conosci il modo in cui i tuoi dati sono archiviati su disco, più velocemente sarai in grado di scrivere le tue query. Se tutto è stato archiviato in sequenza sulla chiave primaria, può essere utile ordinare le chiavi delle primarie restituite da una query nidificata. Inoltre, se è possibile ridurre l'insieme di set di dati che è necessario analizzare in anticipo, farlo. A seconda del sistema in uso, vengono visualizzati circa 1 secondo di trasferimento dei dati per file.

Se hai intenzione di modificare i valori del nome (i varchars) lo cambierei in un tipo di dati con una dimensione massima, impedirà la frammentazione e il trade off è solo qualche byte in più di memoria. Forse una NVARCHAR con un massimo di 100.

Per quanto riguarda i commenti sulla denormalizzazione della tabella. Penso che potrebbe essere meglio archiviare i punti dati in gruppi più grandi (forse come spettri) e quindi fare l'analisi dei dati in Python o in un linguaggio che interagisce con il database. A meno che non si tratti di una procedura guidata SQL.


3
Enfatizzi l'enorme differenza nella latenza del disco rigido rispetto alla memoria, ma i tuoi numeri sono disattivati ​​di un fattore 1000. Se i dischi rigidi hanno una latenza di circa 10 ms e la memoria 10 n, le latenze non differiscono di un fattore 1.000 ma di un fattore di 1.000.000!
spectre256,

6

Per me sembra uno scenario di utilizzo in cui si desidera qualcosa come un "archivio di colonne relazionali" come descritto qui .

Potrei fraintendere il design, ma se si ha a che fare principalmente con una grande raccolta di array, memorizzarli in tipiche tabelle orientate alle righe significa che ogni elemento è simile a una sezione. Se sei interessato a guardare le sezioni in un modo tipico, questo ha senso, ma potrebbe essere meno efficiente se stai davvero guardando intere colonne alla volta.

Quando si recuperano le matrici, non solo potrebbe non essere necessario unirle a un'altra tabella risultante dalla normalizzazione, ma è possibile recuperare le serie come una matrice anziché come un hash.

Potrei davvero fraintendere il problema e non sto nemmeno suggerendo una soluzione specifica.

Ecco un altro discorso che può essere rilevante, anche se non è davvero una soluzione attuale o distribuibile.



5

Si ma...

Ho lavorato con tabelle con 2 miliardi di righe. Tuttavia, ci si aspettava che solo le query che utilizzavano PK fossero veloci.

Ancora più importante, l'hardware aveva abbastanza RAM per adattarsi a interi tavoli in memoria. Quando questo è diventato un problema (massimo a 96 GB a quel tempo), è andato per il partizionamento verticale, mantenendo le dimensioni della tabella impostata su ogni macchina abbastanza piccola da stare ancora nella memoria. Inoltre, le macchine erano collegate tramite fibra da 10 Gb, quindi il throughput di rete non era un grosso problema.

BTW. il tuo schema sembra qualcosa, che potrebbe adattarsi alla soluzione NoSQL, usando run_idcome chiave di hashing per gli spettri e spectrum_idcome chiave di hashing per i punti dati.


4

Ho scritto su questo argomento sul mio blog: http://www.tocker.ca/2013/10/24/improving-the-performance-of-large-tables-in-MySQL.html

Per ripetere alcuni dei punti chiave:

  • Gli alberi B si degradano man mano che diventano più grandi e non si adattano alla memoria (qui MySQL non è il solo).
  • InnoDB ha alcune funzionalità che aiutano a sostenere alcune prestazioni (modifica del buffer; precedentemente chiamato 'insert buffer').
  • Anche il partizionamento può aiutare.

Nei commenti del mio post Tim Callaghan è collegato a questo: http://www.tokutek.com/resources/benchmark-results/benchmarks-vs-innodb-hdds/#iiBench

Che mostra l'inserimento di 1 miliardo di righe usando il benchmark iibench.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.