:: DEVELOPER ZONE
Die Zeit, einen Datensatz einzufügen, besteht ungefähr aus:
Verbindung: (3)
Anfrage an den Server schicken: (2)
Anfrage parsen: (2)
Datensatz einfügen: (1 x Größe des Datensatzes)
Indexe einfügen: (1 x Anzahl der Indexe)
Schließen: (1)
Wobei die Zahlen in etwa proportional zur Gesamtzeit sind. Diese Berechnung zieht den anfänglichen Overhead, um Tabellen zu öffnen, nicht in Betracht (was einmal für jede gleichzeitig laufende Anfrage gemacht wird).
Die Größe der Tabelle verlangsamt das Einfügen von Indexen um N log N (B-Bäume).
Einige Möglichkeiten, die Geschwindigkeit von Einfügeoperationen zu steigern:
Wenn Sie viele Zeilen vom selben Client aus zur gleichen Zeit einfügen,
benutzen Sie mehrfache Werte (Liste) im INSERT-Statements. Das geht
viel schneller (in manchen Fälle um Faktoren) als separate
INSERT-Statements zu benutzen. Tunen Sie die
myisam_bulk_insert_tree_size-Variable, um das sogar noch zu
beschleunigen. See Abschnitt 5.5.5.4, „SHOW VARIABLES“.
Wenn Sie viele Zeilen von unterschiedlichen Clients aus einfügen, können
Sie mehr Geschwindigkeit erzielen, wenn Sie das INSERT DELAYED-Statement benutzen. See Abschnitt 7.4.3, „HANDLER-Syntax“.
Beachten Sie, dass Sie mit MyISAM-Tabellen Zeilen zur selben Zeit
einfügen können, zu der SELECTs laufen, wenn es keine gelöschten
Zeilen in den Tabellen gibt.
Wenn Daten in eine Tabelle aus einer Textdatei eingeladen werden, benutzen
Sie LOAD DATA INFILE. Das ist üblicherweise 20 mal schneller als
viele INSERT-Statements zu benutzen. See Abschnitt 7.4.9, „LOAD DATA INFILE-Syntax“.
Mit etwas zusätzlicher Mühe ist es möglich, LOAD DATA INFILE noch
schneller laufen zu lassen, wenn die Tabelle viele Indexe hat. Gehen Sie
wie folgt vor:
Optional erzeugen Sie die Tabelle mit CREATE TABLE, zum Beispiel mit
mysql oder über die Perl-DBI.
Führen Sie ein FLUSH TABLES-Statement oder den Shell-Befehl
mysqladmin flush-tables aus.
Geben Sie myisamchk --keys-used=0 -rq /pfad/zu/db/tabelle ein.
Dadurch entfernen Sie die Benutzung aller Indexe von der Tabelle.
Fügen Sie Daten in die Tabelle mit LOAD DATA INFILE ein. Dadurch
werden keine Indexe aktualisiert, was deswegen sehr schnell läuft.
Wenn Sie in Zukunft nur noch aus der Tabelle lesen, benutzen Sie
myisampack, um sie kleiner zu machen. See Abschnitt 8.1.2.3, „Kennzeichen komprimierter Tabellen“.
Erzeugen Sie die Indexe mit myisamchk -r -q /pfad/zu/db/tabelle neu.
Hierdurch wird der Index-Baum im Speicher erzeugt, bevor er auf die Platte
geschrieben wird, was viel schneller ist, weil viele Suchvorgänge auf
Platte vermieden werden. Der sich ergebende Index-Baum ist ausserdem
perfekt ausbalanciert.
Führen Sie ein FLUSH TABLES-Statement oder den Shell-Befehl
mysqladmin flush-tables aus.
Diese Prozedur wird in Zukunft in LOAD DATA INFILE eingebaut werden.
Ab MySQL 4.0 können Sie auch ALTER TABLE tabelle DISABLE KEYS anstelle von myisamchk --keys-used=0 -rq /pfad/zu/db/tabelle
und ALTER TABLE tabelle ENABLE KEYS anstelle von myisamchk -r -q /pfad/zu/db/tabelle benutzen. Damit können Sie auch die FLUSH TABLES-Schritte überspringen.
Sie können die Einfügegeschwindigkeit steigern, indem Sie Tabellen sperren:
mysql> LOCK TABLES a WRITE; mysql> INSERT INTO a VALUES (1,23),(2,34),(4,33); mysql> INSERT INTO a VALUES (8,26),(6,29); mysql> UNLOCK TABLES;
Der hauptsächliche Geschwindigkeitsunterschied liegt darin, dass der
Index-Puffer nur einmal auf Platte zurück geschrieben wird, nachdem alle
INSERT-Statements fertig sind. Normalerweise würden die Index-Puffer
so oft zurück geschrieben wie es INSERT-Statements gibt. Das Sperren
wird nicht benötigt, wenn Sie alle Zeilen mit einem einzigen Statement
einfügen können.
Durch das Sperren wird auch die Gesamtzeit von Tests auf mehrere Verbindungen gesenkt, aber die maximale Wartezeit für einige Threads wird erhöht (weil sie auf Sperren warten). Beispiel:
Thread 1 führt 1000 Einfügevorgänge durch. Thread 2, 3 und 4 fügen 1 Einfügevorgang durch. Thread 5 führt 1000 Einfügevorgänge durch.
Wenn Sie kein Sperren benutzen, sind die Threads 2, 3 und 4 vor 1 und 5 fertig. Wenn Sie Sperren benutzen, sind 2, 3 und 4 wahrscheinlich nicht vor 1 oder 5 fertig, aber die Gesamtzeit sollte etwa 40% geringer sein.
Weil INSERT-, UPDATE- und DELETE-Operationen in MySQL
sehr schnell sind, erhalten Sie bessere Performance über alles, wenn Sie um
alles herum Sperren hinzufügen, was mehr als etwa 5 Einfügeoperationen oder
Aktualisierungen (Updates) in einer Zeile durchführt. Wenn Sie sehr viele
Einfügeoperationen in einer Zeile durchführen, können Sie ein LOCK TABLES machen, gefolgt von einem gelegentlichen UNLOCK TABLES
(etwa alle 1.000 Zeilen), um anderen Threads zu gestatten, auf die Tabelle
zuzugreifen. Das Ergebnis wäre ebenfalls ein netter Geschwindigkeitsgewinn.
Natürlich ist LOAD DATA INFILE zum Einladen von Daten viel
schneller.
Um sowohl für LOAD DATA INFILE als auch für INSERT mehr
Geschwindigkeit zu erzielen, vergrößern Sie den Schlüssel-Puffer.
See Abschnitt 6.5.2, „Serverparameter tunen“.
© 1995-2005 MySQL AB. All rights reserved.
