Der MySQL INSERT Befehl kann ja unterschiedlich verwendet werden und da ich eine Anwendung habe die sehr Insertlastig ist, habe ich mir die unterschiedlichen Möglichkeiten dieses SQL Befehls näher angesehen und ein paar Benchmarks laufen lassen. Die Tests liefen auf einem unbelasteten Server über die PHP cli. Es wurden in jedem Test 1.000.000 Datensätze in eine neu erstellte Tabelle geschrieben. Hier das CREATE TABLE. Wie man sehen kann gibt es 2 Schlüssel die erstellt werden.
CREATE TABLE test
(
id int(10) unsigned NOT NULL auto_increment,
other_id int(10) unsigned NOT NULL,
`hash` char(8) NOT NULL,
`value` text NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY other_id (other_id,`hash`)
)
ENGINE=MyISAM DEFAULT CHARSET=latin1;
Inserts kann man ja als Einzelstatement per SET erstellen oder man benutzt VALUES Listen um mehrere Zeilen mir einem INSERT einzufügen. Das die zweite schneller ist war mir schon klar, aber nicht um wie viel.
Das verzögerte Schreiben der Daten per DELAYED habe ich schon immer benutzt, aber ein weiterer Ansatz war das verzögern des Schreibens des Index per DELAY_KEY_WRITE. Hierbei wird der Index nicht sofort auf die Platte geschrieben. Eigentlich wird er nie auf die Platte geschrieben, außer man gibt es durch ein FLUSH TABLE(S) explizit an. Das hat den Vorteil das man sich ein paar Schreibzugriffe auf die langsame Festplatte spart, die bei mir das Bottleneck ist. Der "Nachteil" ist das man Gefahr läuft das bei einem Absturz des Servers die Index Files unvollständig sind und repariert werden müssen. Das kann man MySQL aber automatisch prüfen und ggf. reparieren lassen.
Als erstes habe ich getestet was der DELAY_KEY_WRITE bei normalen per SET erstellten Statements bringt.
INSERT SET ohne DELAY_KEY_WRITE:
86.0647 Sekunden - inserts/s: 11619.1656
-------------------------------------
INSERT SET mit DELAY_KEY_WRITE:
73.6021 Sekunden - inserts/s: 13586.5689
Man kann schon hier eine deutliche Verbesserung feststellen und man entlastet mit DELAY_KEY_WRITE natürlich die Festplatte. Als nächstes habe ich Inserts mit VALUES Listen getestet und welche Anzahl an Zeilen pro Statement Sinn machen.
INSERT VALUE(100) ohne DELAY_KEY_WRITE:
26.0524 Sekunden - inserts/s: 38384.1796
-------------------------------------
INSERT VALUE(200) ohne DELAY_KEY_WRITE:
25.2528 Sekunden - inserts/s: 39599.5692
Das ist eine Verdreifachung und umso mehr Zeilen man ins Statement drückt umso schneller scheint es zu gehen. Jetzt ging es also nur noch darum die richtige Anzahl an Zeilen pro Statement zu finden und alles zu verknüpfen.
INSERT VALUE(10) mit DELAY_KEY_WRITE:
28.5833 Sekunden - inserts/s: 34985.4635
-------------------------------------
INSERT VALUE(100) mit DELAY_KEY_WRITE:
19.8950 Sekunden - inserts/s: 50263.8854
-------------------------------------
INSERT VALUE(200) mit DELAY_KEY_WRITE:
18.9503 Sekunden - inserts/s: 52769.6131
-------------------------------------
INSERT VALUE(500) mit DELAY_KEY_WRITE:
18.6684 Sekunden - inserts/s: 53566.4545
-------------------------------------
INSERT VALUE(1000) mit DELAY_KEY_WRITE:
18.1983 Sekunden - inserts/s: 54950.1877
Fazit
Das benutzen von VALUES Liste lohnt sich ungemein und das setzen von DELAY_KEY_WRITE bei stark INSERT lastigen Tabellen lohnt sich auch. Ich verwende aktuell irgend was zwischen 300 - 1000 Zeilen pro Statement. Ich will es auch nicht zu groß werden lassen und der Vorteil wird auch immer kleiner.
DELAY_KEY_WRITE habe ich nun auch seit ein paar Monaten im Einsatz ohne Probleme feststellen zu können. Explizite FLUSH TABLES benutze ich auch nicht, aber die nächtlichen Backups führen definitiv eins aus. Wenn der MySQL Server beendet wird, werden die Keys natürlich auch auf die Festplatte geschrieben. Man kann es auf Tabellen Basis wie folgt aktivieren.
ALTER TABLE tablename DELAY_KEY_WRITE=1;
In seiner MySQL Config sollte man noch myisam-recover=BACKUP,FORCE setzen. Damit werden beim starten des MYSQL Servers die Tabellen auf Beschädigung geprüft, gesichert und dann repariert. Zum testen habe ich ihn ein paar mal abgeschossen und es hat problemlos funktioniert.
Related Links