it-swarm.it

Informazioni sulle prestazioni dei database a thread singolo o multithread

H2 è un database a thread singolo con una buona reputazione per quanto riguarda le prestazioni. Altri database sono multi-thread.

La mia domanda è: quando un database multi-thread diventa più interessante di un database single thread? Quanti utenti? Quanti processi? Qual è il grilletto? Qualcuno ha esperienza da condividere?

Sintesi

  • Il solito collo di bottiglia è l'accesso al disco
  • Gli SSD sono veloci, ma fragili (la procedura di fallimento è un must)
  • Una query lunga su un sistema a thread singolo bloccherà tutti gli altri
  • La configurazione del sistema multi-threading può essere complicata
  • I database multithread sono utili anche su sistemi single core
59

Ecco la mia opinione:

Di solito il collo di bottiglia (o la parte più lenta) di un sistema DB è il disco. La CPU raggiunge picchi solo durante le operazioni aritmetiche, l'elaborazione o qualsiasi altra attività svolta dalla CPU. Con un'architettura adeguata, il multithreading può aiutare a compensare il carico di una query sulla CPU invece di eseguire letture/scritture lente del disco. Esistono casi in cui è più veloce calcolare un valore utilizzando i cicli della CPU anziché creare una colonna calcolata (precedentemente salvata su disco) e leggere questa colonna dal disco.

In alcuni RDBMS esiste un DB temporaneo (tempdb) che viene utilizzato da tutti i DB su quell'istanza per l'ordinamento, l'hashing, le variabili temporanee, ecc ... Il multithreading e la suddivisione di questi file tempdb possono essere utilizzati per migliorare il throughput del tempdb , migliorando così le prestazioni complessive del server.

Utilizzando il multithreading (parallelismo), il set di risultati di una query può essere suddiviso per essere elaborato sui diversi core del server, anziché utilizzare un solo core. Questa funzione non migliora sempre le prestazioni, ma ci sono casi in cui lo fa e quindi la funzione è disponibile.

I thread disponibili per il DB vengono utilizzati per vari scopi: lettura/scrittura su disco, connessioni utente, processi in background, blocco/latching, I/O di rete, ecc ... A seconda dell'architettura del sistema operativo, i thread vengono inviati preventivamente alla CPU e vengono gestito usando attese e code. Se la CPU riesce a sgretolare questi thread abbastanza rapidamente, i tempi di attesa saranno bassi. Un DB a più thread sarà più veloce di un DB a thread singolo, poiché in un DB a thread singolo ci sarà il sovraccarico di riciclare un solo thread anziché avere altri gradini prontamente disponibili.

Anche la scalabilità diventa un problema, poiché saranno necessari più thread per gestire ed eseguire il sistema DB scalato.

31
StanleyJohns

Se c'è una cosa che posso dire su MySQL è che InnoDB, il suo motore di archiviazione transazionale (conforme ACID), è effettivamente multithread. Tuttavia, è multithread come LO CONFIGURA !!! Perfino "pronto all'uso", InnoDB funziona alla grande in un singolo ambiente CPU, date le sue impostazioni predefinite. Per sfruttare le funzionalità di multithreading di InnoDB, è necessario ricordare di attivare molte opzioni.

innodb_thread_concurrency imposta il limite superiore sul numero di thread simultanei che InnoDB può tenere aperti. Il miglior numero di round da impostare per questo è (2 X Numero di CPU) + Numero di dischi. [~ # ~] update [~ # ~] : Come ho appreso in prima persona dalla Conferenza di Percona a New York, dovresti impostarlo su 0 per avvisare InnoDB Storage Engine per trovare il numero migliore di thread per l'ambiente in cui è in esecuzione.

innodb_concurrency_tickets imposta il numero di thread che possono bypassare il controllo della concorrenza impunemente. Una volta raggiunto questo limite, il controllo della concorrenza dei thread diventa di nuovo la norma.

innodb_commit_concurrency imposta il numero di transazioni simultanee che possono essere impegnate. Poiché il valore predefinito è 0, la mancata impostazione consente a qualsiasi numero di transazioni di impegnarsi contemporaneamente.

innodb_thread_sleep_delay imposta il numero di millisecondi in cui un thread InnoDB può essere inattivo prima di rientrare nella coda InnoDB. L'impostazione predefinita è 10000 (10 sec).

innodb_read_io_threads e innodb_write_io_threads (entrambi da MySQL 5.1.38) allocare il numero specificato di thread per letture e scritture. L'impostazione predefinita è 4 e il massimo è 64.

innodb_replication_delay impone che il ritardo del thread su uno slave sia innodb_thread_concurrency raggiunto.

innodb_read_ahead_threshold consente letture lineari del numero di estensioni impostato (64 pagine [pagina = 16K]) prima di passare alla lettura asincrona.

Il tempo mi sfuggirebbe se nominassi più opzioni. Puoi leggerli in Documentazione di MySQL .

La maggior parte delle persone non è a conoscenza di queste funzionalità e è abbastanza soddisfatta di InnoDB che sta eseguendo transazioni conformi a ACID. Se modifichi una di queste opzioni, lo fai a tuo rischio e pericolo.

Ho giocato con le istanze di pool di buffer multipli di MySQL 5.5 (162 GB in 9 istanze di pool di buffer) e ho tentato di partizionare automaticamente i dati in memoria in questo modo. Alcuni esperti affermano che questo dovrebbe darti un miglioramento delle prestazioni del 50%. Quello che ho ottenuto è stato un sacco di blocco del thread che ha effettivamente fatto strisciare InnoDB. Sono passato a 1 buffer (162 GB) e tutto andava bene di nuovo al mondo. Immagino che tu abbia bisogno degli esperti Percona a tua disposizione per impostare questo. Domani parteciperò alla conferenza PercQL MySQL a New York e chiederò se l'opportunità si offre.

In conclusione, InnoDB si comporta bene ora in un server multi CPU date le sue impostazioni predefinite per le operazioni multithread. Ottimizzarli richiede molta cura, grande pazienza, ottima documentazione e ottimo caffè (o Red Bull, Jolt, ecc.).

Buongiorno, buonasera e buona notte !!!

AGGIORNAMENTO 2011-05-27 20:11

Sono tornato da Conferenza Percona MySQL a New York giovedì. Che conferenza. Ho imparato molto, ma ho una risposta che esaminerò in merito a InnoDB. Sono stato informato da Ronald Bradford che l'impostazione di innodb_thread_concurrency su 0 consentirà a InnoDB di decidere internamente il miglior modo di agire internamente con la concorrenza dei thread. Lo sperimenterò ulteriormente in MySQL 5.5.

AGGIORNAMENTO 2011-06-01 11:20

Per quanto riguarda una lunga query, InnoDB è conforme ACID e funziona molto bene usando Controllo di concorrenza multipla . Le transazioni dovrebbero essere in grado di trasportare livelli di isolamento (letture ripetibili per impostazione predefinita) che impediscono ad altri di accedere ai dati.

Per quanto riguarda i sistemi multi core, InnoDB ha fatto molta strada. In passato, InnoDB non poteva funzionare bene in un ambiente multicore. Ricordo di dover eseguire più istanze mysql su un singolo server per far sì che più core distribuissero i vari processi mysqld attraverso le CPU. Questo non è più necessario, grazie a Percona e successivamente a MySQL (eh, Oracle, dicendo che mi fa ancora vomitare), poiché hanno sviluppato InnoDB in un motore di archiviazione più maturo che può accedere ai core con semplicità senza molta ottimizzazione. L'attuale istanza di InnoDB oggi può funzionare bene in un singolo server core.

49
RolandoMySQLDBA

Non appena si hanno più utenti o processi simultanei o anche un singolo processo con accesso al database multi-thread, avere un database che supporta il thread diventerà potenzialmente interessante.

H2 è thread-safe, ma serializza tutte le richieste al database, che può diventare un potenziale problema di prestazioni in uno scenario di carichi pesanti. Se questo è effettivamente il caso di un particolare progetto dipende da una combinazione dei requisiti di prestazione, dal numero di thread/utenti/processi che accedono al database, dalla frequenza delle query eseguite da questi thread e dalle prestazioni medie e peggiori del tuo interrogazioni.

Ad esempio, se i tuoi requisiti di prestazione devono avere una risposta entro un secondo, non hai più di 10 utenti simultanei che eseguono una singola query che impiega 0,05 secondi per essere eseguiti, un database a thread singolo ti consentirebbe comunque di raggiungere quegli obiettivi (anche se multithread probabilmente darebbe già un notevole incremento delle prestazioni). Dato lo stesso scenario con una singola potenziale query con prestazioni nel caso peggiore di mezzo secondo, la serializzazione dell'accesso al database non ti consentirà più di raggiungere i tuoi obiettivi di prestazione.

Se al momento stai usando H2 sul tuo progetto, ti consiglierei di eseguire un profiler contro la tua base di codice in uno scenario di caricamento (basta dare il via a un numero x di thread che colpiscono il tuo codice contemporaneamente usando alcune usecase tipiche). Questo ti fornirà metriche effettive riguardanti le prestazioni e i colli di bottiglia nella tua base di codice, invece di limitarti a teorizzare. Se questo mostra che le tue richieste trascorrono gran parte del loro tempo in attesa di accedere al database, è tempo di passare a un database thread.

11
Luke Hutteman

Da quello che posso dire, "single threaded" è un po 'un termine improprio per H2. Il punto è che serializza tutte le transazioni (cioè le fa una alla volta).

La domanda cruciale per sapere se è "ok" o no per la tua applicazione non è "Quanti utenti?" o anche "Quanti processi?", ma "Quanto dureranno le mie transazioni?"

Se tutte le tue transazioni sono sub-second che potrebbero andare bene, se alcune richiedono diverse ore per il completamento, ciò potrebbe non andare bene poiché tutte le altre transazioni in sospeso aspetteranno che finiscano. La decisione se "va bene" o meno dipenderà dai propri requisiti di prestazione, ovvero da quanto tempo è accettabile attendere che i miei utenti colpiscano il database con le transazioni.

--MODIFICARE

Sembra che H2 non serializzi realmente le transazioni - solo DML. In altre parole, molti aggiornamenti brevi all'interno di un'unica transazione lunga non bloccheranno altri aggiornamenti . Tuttavia, a meno che non si stia utilizzando funzionalità sperimentale MVCC , il blocco della tabella significa che ciò ha un effetto simile nella pratica. Esiste anche una funzione "multi_threaded" sperimentale ma non può essere utilizzata contemporaneamente a MVCC

Citando bit e pezzi dal sito PostgreSQL ... Si noti che non ho assolutamente idea dei meriti di questi argomenti - semplicemente non rientravano in un commento.

Dallo sviluppatore FAQ ("Perché i thread non vengono utilizzati ..."):

http://wiki.postgresql.org/wiki/Developer_FAQ#Why_don.27t_you_use_threads.2C_raw_devices.2C_async-I.2FO.2C_.3Cinsert_your_favorite_wizz-bang_feature_here.3E.3F

I thread non sono attualmente utilizzati al posto di più processi per i back-end perché: (...)

  • Un errore in un back-end può danneggiare altri back-end se sono thread all'interno di un singolo processo
  • I miglioramenti della velocità con i thread sono piccoli rispetto al tempo di avvio del back-end rimanente.
  • La condivisione di mapping eseguibili di sola lettura e l'uso di shared_buffers significa che i processi, come i thread, sono molto efficienti in termini di memoria
  • La creazione e la distruzione regolari di processi aiuta a proteggere dalla frammentazione della memoria, che può essere difficile da gestire in processi a lungo termine

Dall'elenco Todo ("Funzionalità che non vogliamo"):

http://wiki.postgresql.org/wiki/Todo#Features_We_Do_Not_Want

Tutti i back-end in esecuzione come thread in un singolo processo (non desiderato)

Ciò elimina la protezione del processo che otteniamo dalla configurazione corrente. La creazione di thread è di solito lo stesso overhead della creazione di processi su sistemi moderni, quindi non è saggio usare un modello thread puro, e MySQL e DB2 hanno dimostrato che i thread introducono tutti i problemi che risolvono. (...)

Quindi, ancora una volta ... Non ho assolutamente idea dei meriti di cui sopra. Era semplicemente troppo lungo per inserirsi in un commento.

5