Utilizzate MySQL per eseguire regolarmente join multidirezionali su oltre 100 GB di tabelle?


11

Background :
ho creato un'applicazione Web che vorrei poter ridimensionare ragionevolmente bene. So di non essere Google o Twitter, ma la mia app utilizza una quantità abbastanza grande di dati per ciascun utente e quindi ha requisiti di dati abbastanza elevati. Voglio essere pronto a ridimensionare ragionevolmente bene senza dover riprogettare tutto in seguito.

Mi considero uno sviluppatore di software, non un esperto di database. Ecco perché sto postando qui. Spero che qualcuno con molta più esperienza nel database possa darmi consigli.

Con un numero relativamente elevato di utenti, ma nulla di simile ai numeri di Facebook, mi aspetto di avere un DB simile a questo:

Un "grande tavolo":

  • 250 milioni di dischi
  • 20 colonne
  • Circa 100 GB di dati
  • Ha una chiave esterna indicizzata bigint (20)
  • Ha una colonna index_id varchar (500) indicizzata
  • Ha una colonna "value" int (11)

4 altri tavoli:

  • 10 milioni di record ciascuno
  • Circa 2-4 GB di dati ciascuno
  • ognuna di queste tabelle ha 4 - 8 colonne
  • una colonna è datetime data_creata
  • una colonna è la colonna varchar (500) string_id
  • una o due colonne di ciascuna di queste tabelle saranno selezionate in un join

Una di queste tabelle viene utilizzata per l'archiviazione delle medie - il suo schema è bigint (20) id, varchar (20) string_id, datetime date_created, float average_value

Cosa voglio fare - due query relativamente costose:

  1. Calcola nuovi valori medi:

    • Utilizzando una chiave esterna, selezionare fino a diversi milioni di record separati dalla tabella grande.
    • Calcola una nuova media, raggruppando per string_id.
    • Inserisci i risultati nella tabella delle medie.
    • Come attualmente costruito, questa query utilizza due join.
  2. Crea record non normalizzati di sola lettura per servire gli utenti:

    • Utilizzare una chiave esterna per selezionare ovunque tra 1.000 e 40.000 record dal tavolo grande.
    • Unisciti a ciascuna delle altre quattro tabelle sul record più recente con la colonna ID stringa.
    • Inserisci i risultati in una tabella non normalizzata.
    • Questi record sono utilizzati dal front-end per visualizzare informazioni agli utenti.
    • Come attualmente costruito, questa query utilizza quattro join.

Ho intenzione di eseguire ciascuna di queste costose query su un database back-end batch che invierà i suoi risultati a un server DB front-end in tempo reale che gestisce le richieste degli utenti. Queste query verranno eseguite a intervalli regolari. Non ho deciso con che frequenza. La query media potrebbe essere eseguita forse una volta al giorno. La query di de-normalizzazione dovrà essere più frequente, forse ogni pochi minuti.

Ognuna di queste query attualmente viene eseguita in pochi secondi in MySQL su una macchina di fascia bassa con un set di dati con record da 100K nella "tabella grande". Sono preoccupato sia della mia capacità di ridimensionamento che dei costi del ridimensionamento.

Domande :

  1. Questo approccio sembra valido? C'è ovviamente qualcosa di sbagliato in questo dal punto di vista generale?
  2. Un RDBMS è lo strumento giusto o dovrei guardare altre soluzioni "big data" come qualcosa della famiglia Hadoop? La mia inclinazione è quella di usare un RDBMS perché i dati sono strutturati e si adattano perfettamente al modello relazionale. Ad un certo punto, però, capisco che potrei non essere più in grado di utilizzare un RDBMS. È vero? Quando sarebbe necessario questo interruttore?
  3. Funzionerà? Queste query possono essere eseguite in un tempo ragionevole? Posso aspettare forse ore per la query n. 1, ma la query n. 2 dovrebbe finire in pochi minuti.
  4. Cosa devo considerare dal punto di vista hardware? Quali sono i miei colli di bottiglia nella RAM e nella CPU? Presumo che mantenere gli indici nella RAM sia importante. C'è qualcos'altro che dovrei considerare?
  5. Ad un certo punto probabilmente dovrò partizionare i miei dati e usare più server. Il mio caso d'uso sembra essere già in quella categoria o sarò in grado di ridimensionare una singola macchina in verticale per un po '? Funzionerà con 10 volte i dati? 100x?

Questo è difficile rispondere a fondo. Forse stai meglio facendo ricerche sulle caratteristiche delle prestazioni delle query MySQL in generale, quindi sai cosa puoi aspettarti .; Una cosa che puoi sempre fare ovviamente è mettere 20 dischi nel server in modo da poter leggere a 3 GB / s circa. Ma penso che tu stia cercando una risposta completa solo al software.
usr

Risposte:


4

Hai provato ad accumulare più dati e confrontarli? 100.000 righe non sono rilevanti. Prova 250M o 500M come ti aspetti che dovrai gestire e vedere dove si trovano i colli di bottiglia.

Un RDBMS può fare molte cose se presti molta attenzione ai limiti e cerchi di lavorare con i punti di forza del sistema. Sono eccezionalmente bravi in ​​alcune cose e terribili in altre, quindi dovrai sperimentare per essere sicuro che sia la soluzione giusta.

Per alcuni processi di elaborazione batch, non è davvero possibile battere i file flat, caricare i dati nella RAM, distruggerli utilizzando una serie di loop e variabili temporanee e scaricare i risultati. MySQL non sarà mai, mai in grado di eguagliare quel tipo di velocità, ma se sintonizzato correttamente e usato correttamente può arrivare in un ordine di grandezza.

Quello che vorrai fare è investigare come i tuoi dati possono essere partizionati. Hai una grande serie di dati con troppi collegamenti incrociati per poterli dividere o ci sono luoghi naturali per partizionarli? Se riesci a partizionarlo non avrai una tabella con un intero mucchio di righe, ma potenzialmente molte di quelle significativamente più piccole. Le tabelle più piccole, con indici molto più piccoli, tendono a funzionare meglio.

Dal punto di vista hardware, dovrai provare per vedere come si comporta la tua piattaforma. A volte la memoria è essenziale. Altre volte è I / O del disco. Dipende davvero da cosa stai facendo con i dati. Dovrai prestare molta attenzione all'utilizzo della tua CPU e cercare alti livelli di IO in attesa di sapere dove si trova il problema.

Quando possibile, dividi i tuoi dati su più sistemi. Puoi usare MySQL Cluster se ti senti coraggioso o semplicemente girare molte istanze indipendenti di MySQL in cui ognuna memorizza una parte arbitraria del set di dati completo usando uno schema di partizionamento che ha senso.


@tadman Grazie per il tuo consiglio. Mi rendo conto che non c'è sostituto per provarlo. Non l'ho confrontato con 250 milioni di righe perché volevo prima assicurarmi che non ci fosse ovviamente nulla di sbagliato nel mio approccio. Sembra che non ci sia. Inoltre, ottenere così tanti dati e farlo in modo un po 'realistico è una sfida che non ho ancora capito come risolvere. Ho alcuni modi potenziali per partizionare i dati. Immagino che dopo proverò semplicemente ad aumentare i miei dati e vedrò come funziona in diversi checkpoint - 1M, 10M, 100M, ecc.
xnickmx,

1

Tabelle di riepilogo.

Ogni giorno, calcola le informazioni aggregate per i dati del giorno. Mettilo nelle tabelle "di riepilogo". Fai le tue domande contro di loro. Facilmente 10 volte più veloce.

Per ulteriori discussioni, si prega di fornire

  • MOSTRA CREA TABELLA (così com'è ora)
  • Dimensioni della tabella (che hai menzionato)
  • SELEZIONI proposte

Alcune cose ovvie ...

  • BIGINT è raramente garantito. Ci vogliono 8 byte. INT UNSIGNED accetta 4 e consente valori 0..4 miliardi. E c'è MEDIUMINT, ecc.
  • Più indici nella tabella 'fact' sono di solito un grave problema di prestazioni, specialmente per gli INSERT. Stai riscontrando un problema lì?
  • DATETIME è 8 byte; TIMESTAMP è 4
  • I VINCOLI ESTERI CHIAVE espliciti sono carini, ma costosi
  • I JOIN possono o meno essere un problema di prestazioni; bisogno di vedere SELEZIONA e CREA.
  • 100 GB sono di buone dimensioni per un "grande" database MySQL; Ho il sospetto che potrebbe essere fatto funzionare senza Hadoop, ecc. Ora mi occupo di uno di questi db - la maggior parte delle pagine dell'interfaccia utente risponde in meno di un secondo anche se i dati sono abbastanza coinvolti.
  • A un certo punto "eliminerai" i dati? (Questo porta al caso d'uso principale per il partizionamento.)

"Più piccolo -> più memorizzabile nella cache -> più veloce


0

Per pubblicare i tuoi dati front-end, a meno che non ci siano sempre goccioline di inserti, non puoi davvero battere usando i trigger per inserire in viste materializzate che sono mantenute sincronizzate con il back-end ma ottimizzate per servire i dati. Naturalmente, è necessario ridurre al minimo i join, ecc., Ecc. In questi trigger. Una strategia che ho usato è quella di mettere in coda questi inserti / aggiornamenti in una tabella intermedia e poi inviarli più tardi ogni minuto circa. È molto più facile inviare un record di 4 GB di record. Lo streaming di 4 GB di dati richiede molto tempo anche se è possibile trovare rapidamente i record che si stanno cercando.

Sono d'accordo con Tadman. La cosa migliore è profilarla con il tipo di dati che ti aspetti sul tipo di sistema che desideri.


Come ho accennato nel mio post, le viste dipendono da una query che utilizza quattro join su tabelle con decine di milioni di record, quindi non vedo davvero come una vista materializzata possa aiutare.
xnickmx,

I trigger potrebbero non essere abbastanza veloci per questo database di dimensioni. Quanti INSERT al secondo stanno accadendo?
Rick James,

1
@xnickmx Se non ci sono così tanti inserimenti / aggiornamenti, i trigger rendono facile / performante mantenere sincronizzati i dati denormalizzati. Se deve essere più veloce per inserimenti / aggiornamenti, mettili in coda con qualcosa del genere: blog.shlomoid.com/2008/04/… o creane uno tuo. In questo modo non è necessario unirsi ai 100 milioni di tabelle delle righe esistenti per ottenere i nuovi dati poiché quando il trigger si attiva, si sfrutta il fatto di conoscere i nuovi dati in quel momento e si può semplicemente denormalizzarli come parte del tx o metterlo in coda per la denormalizzazione in seguito.
wes.stueve,

@RickJames concordato. È necessario tenere conto della quantità di inserti per questo tipo di strategia e della velocità con cui devono essere elaborati.
wes.stueve,
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.