Warum ist 'LOAD DATA INFILE' schneller als normale INSERT-Anweisungen?

22

Ich habe einen Artikel gelesen, in dem erwähnt wurde , dass mit der Anweisung, mit der aus CSV-Dateien gelesen und die Daten in eine Datenbank eingefügt werden , 60.000 Einfügungen pro SekundeLOAD DATA IN FILE erzielt werden können.

Warum sollte es sich von normalen Einsätzen unterscheiden?

EDIT:
Ich habe die Hin- und Rückfahrt reduziert, indem ich nur eine INSERTAnweisung aufgerufen habe:

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');

Was ist damit?

ALH
quelle
Ich habe einen Artikel über Medium geschrieben, in dem erweiterte Inserts verglichen werden mit LOAD DATA INFILE: High-Speed-Inserts mit MySQL . Fazit: LOAD DATA INFILEMit erweiterten Einsätzen erreichen Sie 65% der Leistung . Ich habe 240.000 Einfügungen / Sekunde auf moderner Hardware.
Benjamin

Antworten:

26

LOAD DATA INFILE und Extended INSERTs haben jeweils ihre eigenen Vorteile.

LOAD DATA INFILE wurde zum Massenladen von Tabellendaten in einer einzigen Operation zusammen mit Schnickschnack entwickelt, um folgende Aufgaben auszuführen:

  • Anfangszeilen überspringen
  • Überspringen bestimmter Spalten
  • Transformieren bestimmter Spalten
  • Laden bestimmter Spalten
  • Behandlung von Problemen mit doppelten Schlüsseln

Für das Parsen wird weniger Aufwand benötigt

Auf der anderen Seite ist es sinnvoll, INSERT zu erweitern, wenn Sie nur 100 statt 1.000.000 Zeilen importieren.

Beachten Sie, dass mysqldump für erweiterte INSERTs entwickelt wurde, um das Entwerfen von Tabellen zusammen mit Daten zu ermöglichen, da dabei Hunderte oder Tausende von Zeilen pro INSERT eingefügt werden. LOAD DATA INFILE erzeugt immer eine physikalische Zweiteilung zwischen Schema und Daten.

Aus Sicht der Anwendung ist LOAD DATA INFILE auch unempfindlicher gegenüber Schemaänderungen als erweiterte INSERTs.

Mit LOAD DATA INFILE kann man gut, schlecht und hässlich hin und her gehen. Unabhängig davon, welche Technik Sie verwenden, müssen Sie immer die bulk_insert_buffer_size festlegen . Warum?

Gemäß der MySQL-Dokumentation zu bulk_insert_buffer_size:

MyISAM verwendet einen speziellen baumartigen Cache, um Masseneinfügungen für INSERT ... SELECT, INSERT ... VALUES (...), (...), ... und LOAD DATA INFILE zu beschleunigen, wenn Daten zu nonempty hinzugefügt werden Tabellen. Diese Variable begrenzt die Größe des Cache-Baums in Bytes pro Thread. Wenn Sie den Wert auf 0 setzen, wird diese Optimierung deaktiviert. Der Standardwert ist 8 MB.

Ich habe jahrelang gesehen, dass Client für Client dies nicht eingestellt und auf 8 MB belassen hat. Wenn sie sich dann entscheiden, LOAD DATA INFILE zu verwenden oder mysqldumps zu importieren, können sie einen Fehler feststellen. Normalerweise empfehle ich die Einstellung auf moderate 256 MB. In einigen Fällen 512M.

Sobald Sie einen ausreichend großen INSERT-Puffer haben, wird die Verwendung einer der beiden Techniken akademisch und auf die persönliche Wahl reduziert. Bei Anwendungen, bei denen Sie INSERT auf Anfrage nur zu 100 Zeilen aufteilen, sollten Sie sich an erweiterte INSERTs halten.

Um ehrlich zu sein: LOAD DATA INFILE ist schneller als normale INSERT-Anweisungen, da die Konfiguration nicht berücksichtigt wird. Selbst wenn Sie einen Benchmark zwischen LOAD DATA INFILE und Extended INSERTs mit einer korrekten bulk_insert_buffer_size einrichten, können die Nanosekunden, die beim Parsen jeder Zeile eingespart werden, bestenfalls zu Gunsten von LOAD DATA INFILE zu nominalen Ergebnissen führen.

Fahren Sie fort und fügen Sie dies zu my.cnf hinzu

[mysqld]
bulk_inset_buffer_size=256M

Sie können es auch nur für Ihre Sitzung festlegen, bevor Sie erweiterte INSERTs starten

SET bulk_insert_buffer_size= 1024 * 1024 * 256;

UPDATE 19.07.2012 14:58 EDT

Um den Überblick zu behalten, ist der Bulk-Insert-Puffer nur zum Laden von MyISAM-Tabellen nützlich, nicht für InnoDB. Ich schrieb einen neueren Beitrag zum Massenladen von InnoDB: MySQL-Laden von Infile stecken auf der Festplatte

RolandoMySQLDBA
quelle
4

Die meisten Datenbankverwaltungssysteme verfügen über eine Massenladeeinrichtung zum schnellen Laden großer Datenmengen. Ein INSERTKontoauszug enthält eine erhebliche Menge an Gepäck pro Kontoauszug - Sperren, Transaktionsabgrenzung, Überprüfung der referenziellen Integrität, Zuweisung von Ressourcen, E / A, die auf Kontoauszugsbasis durchgeführt werden muss.

Masseneinfügungsoperationen rationalisieren den Prozess, sodass dieses Zeug viel, viel weniger Overhead pro Zeile hat. Ein DBMS kann Datenmengen um Größenordnungen schneller als durch Einfügeanweisungen laden.

Betroffen vonTunbridgeWells
quelle
3

Das Parsen und Ausführen einzelner INSERTAnweisungen ist mit einem viel höheren Aufwand verbunden als das Aufteilen einer CSV-Datei in Spalten und deren direktes Laden.

Jede INSERTAnweisung muss einzeln von der MySQL-Engine analysiert und auf Gültigkeit überprüft werden - dies verbraucht zusätzliche CPU-Ressourcen und erfordert auch mehr Client-Server-Roundtrips. Dies muss beim Massenladen über nicht geschehen LOAD DATA INFILE. Es gibt auch Optimierungen, die beim LOAD DATA INFILELaden in eine leere Tabelle vorgenommen werden können. Weitere Informationen finden Sie unter diesem Link .

Philᵀᴹ
quelle
siehe den EDIT-Teil meiner Frage.
ALH
Beachten Sie, dass bei der Verwendung von vorbereiteten Anweisungen kein Parsing-Overhead entsteht.
Benjamin