velocità di caricamento lenta dei dati da mysqldump


21

Ho un database MySQL di dimensioni moderate con circa 30 tabelle, alcune delle quali sono 10 milioni di record, circa 100 milioni. Il mysqldumpdi tutte le tabelle (in file separati) è abbastanza veloce, richiede forse 20 minuti. Genera circa 15 GB di dati. I file più grandi scaricati sono nella gamma di 2 GB.

Quando carico i dati in MySQL su un'altra scatola, una macchina a sei core da 8 GB, ci vuole sempre. Facilmente 12 ore o più.

Sto solo eseguendo il client mysql per caricare il file, ad es

mysql database < footable.sql

direttamente con il file direttamente da mysqldump

mysqldump database foo > footable.sql

Chiaramente sto facendo qualcosa di sbagliato. Da dove comincio in modo che possa finire in un tempo ragionevole?

Non sto usando alcun interruttore né sul dump né sul carico.


Puoi anche disattivare la registrazione binaria durante il caricamento della tua discarica
Cédric PEINTRE,

Risposte:


22

Prendi in considerazione questi punti che potrebbero aiutarti in caso di generazione del dump e ripristino.

  1. Utilizzare Extended insertsin discarica.
  2. Scarica con il --tabformato in modo da poter usare mysqlimport, che è più veloce di mysql < dumpfile.
  3. Importa con più thread, uno per ogni tabella.
  4. Utilizzare un motore di database diverso, se possibile. l'importazione in un motore fortemente transazionale come innodb è terribilmente lenta. L'inserimento in un motore non transazionale come MyISAM è molto più veloce.
  5. Disattiva i controlli delle chiavi esterne e attiva il commit automatico.
  6. Se stai importando su innodb l'unica cosa più efficace che puoi fare è inserire innodb_flush_log_at_trx_commit = 2my.cnf, temporaneamente mentre l'importazione è in esecuzione. puoi rimetterlo a 1 se hai bisogno di ACID

Provaci..


Il tuo suggerimento con innodb_flush_log_at_trx_commit = 2mi ha salvato la giornata. L'importazione di un dump da 600 MB (come un'unica grande transazione) avrebbe richiesto 6 ore, ma con questa impostazione temporanea, è stata eseguita in 30 minuti!
Daniel Marschall,

1
Le cose che vorresti sapere prima di provare a caricare un database 80gig da un dump 4 giorni dopo aver premuto 'enter' ... :)
Dmitri DB

7

Oltre alla risposta di Abdul , vorrei sottolineare l'importanza --disable-keysdell'opzione, che spegne le chiavi fino a quando tutti i dati non vengono caricati per una tabella. Questa opzione è abilitata come parte del --opttoggle, che è abilitato di default, ma ha ritenuto importante sottolineare.

Se non si saltano le chiavi durante gli inserimenti, ogni riga inserita ricostruirà l'indice. Un processo estremamente lento.


--disable-keys fa parte di mysqldump? o la ricarica?
Pat Farrell,

sarà aggiunto nel file di dump
Derek Downey il

--optè
attivo

1
This option is effective only for nonunique indexes of MyISAM tables. It has no effect for other tables
Ethan Allen,

7

Ho avuto a che fare molto con questo ultimamente. Puoi sicuramente migliorare le prestazioni delle importazioni eseguendo le importazioni in parallelo. La maggior parte del rallentamento si basa sull'I / O, ma è comunque possibile ottenere un miglioramento del 40% scaricando le tabelle e quindi importandole 4 alla volta.

Puoi farlo con xargs come questo:

ls *.sql -1c | xargs -P4 -I tbl_name sh -c "mysql --user=username --password database < tbl_name"

avere i file compressi con i gzip prima di inviarli a mysql non rallenta nulla principalmente a causa dell'I / O abbassato. I miei tavoli sono stati compressi fino a circa 10: 1, quindi consente di risparmiare molto spazio su disco.

Ho scoperto che su 4 macchine core, l'utilizzo di 4 processi è ottimale, sebbene solo leggermente migliore dell'uso 3. Se si dispone di SSD o RAID veloce, è probabile che si ridimensioni meglio.

Alcune altre cose da notare. Se hai unità settoriali 4k, assicurati di avere key_cache_block_size=4096e myisam_block_size=4K.

Se si utilizzano le tabelle MyISAM, impostare il valore myisam_repair_threads = 2o superiore. Ciò consentirà ai core extra di aiutarti a ricostruire gli indici.

Assicurati di non scambiare affatto. Se lo sei, riduci le dimensioni di innodb_buffer_pool_size.

Penso di aver ottenuto un po 'di accelerazione con innnodb anche da queste opzioni:

innodb_flush_method= O_DIRECT (LINUX ONLY)
innodb_flush_log_at_commit = 0
innodb_doublewrite=0
innodb_support_xa=0
innodb_checksums=0

(gli ultimi tre che non ho testato ampiamente - penso di averli trovati come suggerimenti su Internet.) Nota che innodb_flush_log_at_commit=0può provocare la corruzione con mysql che si interrompe o che si spegne.


Greg, benvenuto nel sito e grazie per la risposta. Potresti fornire alcune fonti o ragionamenti per i tuoi suggerimenti su *_block_sizee myisam_repair_threads? Inoltre, non sono sicuro che dovremmo offrire consigli per ottimizzare le variabili in base a "suggerimenti provenienti da Internet" :)
Derek Downey,

5

Se si dispone principalmente di tabelle MyISAM, è necessario aumentare il buffer di inserimento di massa . Ecco cosa dice la documentazione di MySQL sull'impostazione bulk_insert_buffer_size :

MyISAM utilizza una speciale cache ad albero per rendere più rapidi gli inserimenti di massa per INSERT ... SELECT, INSERT ... VALUES (...), (...), ... e LOAD DATA INFILE quando si aggiungono dati a non vuoto tabelle. Questa variabile limita la dimensione dell'albero della cache in byte per thread. Impostandolo su 0 disabilita questa ottimizzazione. Il valore predefinito è 8 MB.

Ci sono due cose che devi fare

1) Aggiungilo a /etc/my.cnf

[mysqld]
bulk_insert_buffer_size=512M

2) Impostare il valore globale per esso

SET GLOBAL bulk_insert_buffer_size = 1024 * 1024 * 512;

Se non si dispone del privilegio di impostare bulk_insert_buffer_size a livello globale, procedere come segue

service mysql restart

Naturalmente, questo non è per InnoDB.

Da un altro punto di vista, se le tabelle sono InnoDB o MyISAM, se gli indici sono più grandi di quelli della tabella, è possibile che vi siano troppi indici. Di solito mi rendo conto che un ricaricamento di un mysqldump MyISAM dovrebbe impiegare 3 volte il tempo necessario al mysqldump. Ho anche notato che un ricaricamento di un mysqldump di InnoDB dovrebbe richiedere 4 volte il tempo necessario per eseguire il mysqldump.

Se stai superando il rapporto 4: 1 per ricaricare un mysqldump, hai sicuramente uno dei due problemi:

  • troppi indici
  • indici troppo grandi a causa di colonne di grandi dimensioni

Puoi misurare la dimensione dei tuoi dati dal motore di archiviazione con questo:

SELECT IFNULL(B.engine,'Total') "Storage Engine",
CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Data Size", CONCAT(LPAD(REPLACE(
FORMAT(B.ISize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Index Size", CONCAT(LPAD(REPLACE(
FORMAT(B.TSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Table Size" FROM
(SELECT engine,SUM(data_length) DSize,SUM(index_length) ISize,
SUM(data_length+index_length) TSize FROM
information_schema.tables WHERE table_schema NOT IN
('mysql','information_schema','performance_schema') AND
engine IS NOT NULL GROUP BY engine WITH ROLLUP) B,
(SELECT 3 pw) A ORDER BY TSize;

Verifica se gli indici sono quasi grandi quanto i dati o addirittura più grandi

Puoi anche considerare di disabilitare la registrazione binaria in questo modo:

echo "SET SQL_LOG_BIN=0;" > footable.sql
mysqldump --databases foo >> footable.sql

prima di ricaricare lo script


Non so quante volte mi hai salvato la giornata ma sicuramente è stato molto
Dmitri DB

2

Se si ignora del tutto il filesystem e si esegue semplicemente il pipe dell'output di mysqldump direttamente in un processo MySQL, si dovrebbero notare notevoli miglioramenti delle prestazioni. Quanto dipende in ultima analisi dal tipo di unità disco che si sta utilizzando, ma raramente utilizzo più i file di dump indipendentemente dalle dimensioni del database solo per questo motivo.

mysqldump -uxxx -pxxx -hxxx --single-transaction --routines --databases dbname | mysql -uyyy -pyyy -hyyy

1

Secondo le mie esperienze, il disco rigido è il collo di bottiglia. Dimentica i dischi rotanti. L'SSD è migliore, ma di gran lunga il migliore è eseguirlo nella RAM, se hai abbastanza per contenere l'intero database per un breve periodo. Circa:

  1. basta mysqld
  2. sposta i contenuti esistenti di / var / lib / mysql
  3. crea una directory vuota / var / lib / mysql
  4. mount -t tmpfs -o size = 32g tmpfs / var / lib / mysql (regola le dimensioni)
  5. creare un db vuoto (ad es. mysql_install_db o ripristinare i contenuti precedenti)
  6. avvia mysqld
  7. importare
  8. basta mysqld
  9. copia / var / lib / mysql in mysql2
  10. umount mysql; rmdir mysql
  11. sposta mysql2 in mysql
  12. avvia mysqld, sii felice

Per me, un dump di ~ 10G (/ var / lib / mysql che consuma ~ 20G) può essere importato in circa 35 minuti (mydumper / myloader), 45 minuti (mysqldump --tab / mysqlimport), 50 minuti (mysqldump / mysql) , su un Xeon da 3,2 GHz a 2x6 core.

Se non hai abbastanza RAM in una singola macchina, ma hai diversi computer uno accanto all'altro con una rete veloce, sarebbe interessante vedere se le loro RAM possono essere unite con nbd (dispositivo a blocchi di rete). Oppure, con innodb_file_per_table, puoi probabilmente ripetere il processo sopra descritto per ogni tabella.


Per curiosità ho provato a memorizzare il datadir mysql nella RAM per confrontarlo con un SSD (SSDSC2BB48 per gli interessati) per un database da 2 GB. I risultati furono IDENTICI, entrambi impiegarono 207-209 secondi. Considerando il fatto che devi anche avviare / arrestare mysql e copiare le directory, usare un disco RAM invece dell'SSD è stato molto più lento nel mio caso
Shocker

Se hai impiegato ~ 3-4 minuti, immagino che tu abbia un database significativamente più piccolo di quello di cui tratta questo argomento. Sarebbe interessante conoscere le tue esperienze con database di dimensioni simili a quelle menzionate in questo argomento.
egmont,
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.