Daten möglichst schnell in MySQL importieren

slurp

Neuer Benutzer
Beiträge
2
Hallo Zusammen.

Ich bin ganz neu hier und ich hoffe ihr könnt mir Helfen :)

Ich möchte Daten die ich habe (*.nq-Dateien) in MySQL importieren.
Die Daten liegen im NQuads-Format vor und enthalten somit keine SQL-Insert-Statements, der mysqlimport-Befehl funktioniert daher nicht.
Ich habe mir ein Java-Programm geschrieben, dass diese nq-Dateien parst (Zerlegung in einfache Token) und mittels prepared-Statement in die DB schreibt.
Das Importieren von 5GB Daten dauert bei mir knapp über 2 Stunden :(

Die DB wird nur lokal und somit von nur einem Benutzer genutzt. Ich verwende eine MyISAM und eine InnoDB Tabelle in die ich dieselben Daten schreibe.
Der Flaschenhals in meinem Java-Programm ist die "execute()"-Anweisung des Prepared Statements. Wenn ich diese Anweisung auskommentiere benötigt das Programm knapp 1 Minute für die Ausführung.
Ich suche nun nach einer Möglichkeit diese Daten möglichst schnell in die DB zu pumpen.

Hier meine Tabellen:

CREATE TABLE dbpedia_innodb (
line INT NOT NULL AUTO_INCREMENT ,
one VARCHAR(4000) NULL ,
two VARCHAR(4000) NULL ,
three LONGTEXT NULL ,
four VARCHAR(4000) NULL ,
PRIMARY KEY (line) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;

CREATE TABLE dbpedia_myisam (
line INT NOT NULL AUTO_INCREMENT ,
one VARCHAR(4000) NULL ,
two VARCHAR(4000) NULL ,
three LONGTEXT NULL ,
four VARCHAR(4000) NULL ,
PRIMARY KEY (line) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = latin1;

Kann mir jemand sagen, wie ich die Daten möglichst schnell importiere? Welche Parameter muss ich setzen?
Ich arbeite unter Linux mit MySQL 5.5. Während des Importvorgangs schaue ich mir mittels "iotop" die Festplattenauslastung an und sehe, dass lediglich nur ein paar MB/s oder teilweise nur KB/s in vom mysqld-Prozess geschrieben werden (Festplatte ist aber in Ordnung und schafft rund 90MB/s im Durschnitt). Die CPU-Auslastung liegt bei etwa 50%. Was bremst den Import hier so gewaltig? Ach ja: ich mache etwa alle 8000 Tupel einen Commit. Ist das bei MyISAM überhaupt notwendig?

Vielen Dank das Ihr euch Zeit für mich nehmt!

EDIT:
Das prepared Statement besteht lediglich aus einem simplen "insert into tabelle(one, two,three) values (?,?,?)" also keine komplexe Anfrage.
 
Werbung:

ukulele

Datenbank-Guru
Beiträge
4.394
Für mich hört sich das schon nach einem sinnvollen Weg an aber da ich in MySQL sowas noch nie gemacht habe sehe ich da keinen Fehler und kenne leider auch keine Alternative.

Trotzdem würde ich sicherheitshalber auf SQL Injection hinweisen, nicht das dein Parser da potenziellen Schadecode durchreicht.
 

slurp

Neuer Benutzer
Beiträge
2
Hallo Zusammen.

Vielen Dank für Eure Antworten.

@ukulele:
Bzgl. SQL-Injection: Ich verwende ein Prepared Statement mit Parametern, soweit ich das sehe dürfte sich JDBC darum kümmern. Ich selbst baue keine Strings zusammen und übergebe diese an die DB. Trotzdem vielen Dank für den Hinweis!

@akretschmer:
Danke, kannte ich noch garnicht. Das scheint der richtige Weg zu sein, ein Import mittels "LOAD DATA INFILE" war wesentlich schneller: von etwa 2 Std auf knapp 3 Minuten :).
Was mich hier jetzt quält ist die Frage wie LOAD DATA INFILE arbeitet. Schreibt es die DB-Datei selbst unter Umgehung der gesamten DBMS (nach einem table lock)? Ich weiß zwar, dass bei dieser Variante kein SQL geparst werden muss sondern nur die Daten weitergereicht werden müssen. Aber das dabei ein solcher Zeitunterschied auftritt ist doch recht merkwürdig.
Wie sieht das eigentlich aus, wenn ich BULK-Daten (welche zur Laufzeit generiert werden) in die DB pumpen möchte. Ich müsste in einem solchen Fall dann die Daten vorerst in eine TXT-Datei appenden und dann zb. stündlich/täglich mittels "LOAD DATA INFILE" die Daten in die DB schreiben. Das sieht allerdings sehr unschön aus, dürfte aber wesentlich schneller gehen.

Viele Grüße
 

akretschmer

Datenbank-Guru
Beiträge
9.028
Was mich hier jetzt quält ist die Frage wie LOAD DATA INFILE arbeitet. Schreibt es die DB-Datei selbst unter Umgehung der gesamten DBMS (nach einem table lock)?

Ich weiß nicht, wie MySQL da vorgeht. In PostgreSQL nennt sich das vergleichbare Vorgehen COPY, und da gibt es *keinerlei* Sperren. MVCC. Hängt bei MySQL möglicherweise auch von der Engine ab.

Andreas
 
Werbung:
Oben