Perché "LOAD DATA INFILE" è più veloce delle normali istruzioni INSERT?


22

Ho letto un articolo che menzionava che possiamo ottenere 60.000 inserimenti al secondo usando la LOAD DATA IN FILEdichiarazione, che legge da file CSV e inserisce i dati in un database.

Perché dovrebbe differire dai normali inserti?

EDIT:
ho ridotto il viaggio di andata e ritorno chiamando una sola INSERTdichiarazione:

INSERT INTO tblname
VALUES (NULL,2,'some text here0'),(NULL,2,'some text here1')
    ,(NULL,2,'some text here2'),(NULL,2,'some text here3')
    .....,(NULL,2,'some text here3000');

Che dire di questo?


Ho scritto un articolo su Medium, confrontando inserti estesi vs LOAD DATA INFILE: inserti ad alta velocità con MySQL . In conclusione: è possibile ottenere il 65% delle prestazioni LOAD DATA INFILEdell'utilizzo di inserti estesi. Ho ottenuto 240.000 inserti / secondo su hardware moderno.
Benjamin,

Risposte:


26

LOAD DATA INFILE e INSERT estesi hanno ciascuno i loro vantaggi distinti.

LOAD DATA INFILE è progettato per il caricamento di massa dei dati della tabella in un'unica operazione insieme a campane e fischietti per eseguire suoni come:

  • Saltare le linee iniziali
  • Saltare colonne specifiche
  • Trasformazione di colonne specifiche
  • Caricamento di colonne specifiche
  • Gestione dei problemi con le chiavi duplicate

Per l'analisi è necessario meno sovraccarico

D'altro canto, se si stanno importando solo 100 righe invece di 1.000.000 di righe, INSERT esteso è ragionevole.

Si noti che mysqldump è stato progettato attorno a INSERT estesi per il gusto di trasportare il design della tabella insieme ai dati mentre esegue l'iniezione di centinaia o migliaia di righe per INSERT. LOAD DATA INFILE crea sempre una dicotomia fisica tra schema e dati.

Dal punto di vista dell'applicazione, LOAD DATA INFILE è anche più insensibile alla modifica dello schema rispetto agli INSERT estesi.

Si può andare avanti e indietro nel bene, nel male e nel brutto di usare LOAD DATA INFILE. Indipendentemente dalla tecnica utilizzata, è sempre necessario impostare bulk_insert_buffer_size . Perché?

Secondo la documentazione MySQL su 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.

Per anni, ho visto client dopo client non impostare questo e lasciarlo a 8 MB. Quindi, quando decidono di utilizzare LOAD DATA INFILE o di importare mysqldumps, possono percepire qualcosa di sbagliato. Di solito consiglio di impostarlo su un moderato 256M. In alcuni casi, 512M.

Una volta che hai un buffer INSERT abbastanza grande, l'utilizzo di entrambe le tecniche è reso accademico e si riduce a una scelta personale. Per le applicazioni in cui INSERT in blocco è di appena 100 righe su richiesta, attenersi agli INSERT estesi.

In tutta onestà, dire che LOAD DATA INFILE è più veloce del normale INSERT è una specie di istruzione caricata principalmente perché la configurazione non viene presa in considerazione. Anche se si imposta un benchmark tra LOAD DATA INFILE e INSERT estesi con un bulk_insert_buffer_size corretto, i nanosecondi salvati sull'analisi di ogni riga possono solo produrre risultati nominali al massimo a favore di LOAD DATA INFILE.

Vai avanti e aggiungi questo a my.cnf

[mysqld]
bulk_inset_buffer_size=256M

Puoi anche impostarlo solo per la tua sessione prima di lanciare INSERT estesi

SET bulk_insert_buffer_size= 1024 * 1024 * 256;

AGGIORNAMENTO 2012-07-19 14:58 EDT

Per mantenere le cose in prospettiva, il buffer di inserimento di massa è utile solo per caricare tabelle MyISAM, non InnoDB. Ho scritto un post più recente sul caricamento di massa InnoDB: caricamento Mysql da file bloccato in attesa sul disco rigido


4

La maggior parte dei sistemi di gestione dei database dispone di una funzione di caricamento di massa per il caricamento rapido di grandi volumi di dati. Una INSERTdichiarazione ha una quantità significativa di bagaglio per dichiarazione: blocco, delimitazione delle transazioni, controlli di integrità referenziale, allocazione delle risorse, I / O che devono essere effettuati in base alla dichiarazione.

Le operazioni di inserimento in blocco semplificano il processo in modo che questa roba abbia un sovraccarico molto, molto meno per riga. Un DBMS può caricare in blocco ordini di dati di grandezza più rapidamente rispetto alle istruzioni di inserimento.


3

L'analisi e l'esecuzione di singole INSERTistruzioni comporta un sovraccarico molto maggiore rispetto alla suddivisione di un file CSV in colonne e al loro caricamento diretto.

Ogni INSERTistruzione deve essere analizzata individualmente dal motore MySQL e verificata la validità: ciò consuma risorse CPU aggiuntive e richiede anche più round-trip client <> server. Non è necessario che ciò avvenga durante il caricamento di massa tramite LOAD DATA INFILE. Ci sono anche ottimizzazioni che possono avvenire quando si utilizza LOAD DATA INFILEper caricare in una tabella vuota. Vedi questo link per maggiori informazioni.


vedi la parte EDIT della mia domanda.
ALH,

Si noti che non vi è alcun costo di analisi durante l'utilizzo di istruzioni preparate.
Benjamin,
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.