Viel zu langsame DerbyDB

Status
Nicht offen für weitere Antworten.

Paladin

Bekanntes Mitglied
Hi,

ich versuche gerade in eine Derby Datenbank 200000 Zeilen und mehr einzufügen. Bis zu 10000 Zeilen funktioniert das auch in einer annehmbaren Geschwindigkeit aber alles jenseits von 50000 Zeilen dauert extrem lange. Ich hab zum Beispiel versucht 200000 Zeilen einzufügen und hab den Versuch nach etwas mehr als 10min abgebrochen weils einfach zu lange dauert.

Liegt es an meinem Sourcecode? Ich kann mir eigentlich nicht vorstellen, dass Derby schon bei 50000 Zeilen Probleme bekommt.

Hier also der Sourcecode mit dem ich in die Datenbank einfüge:
trows = Anzahl der einzufügenden Zeilen (long)
in = BufferedReader(FileReader(File))


Code:
   for(i1=0;i1<trows;i1++) {
      try {				
         hsqlstatement.execute(in.readLine());			
      } catch (Exception e) {
         e.printStackTrace();
      }
}

Die Tabelle Vergleich wird mit folgendem sql Befehl angelegt:
CREATE TABLE Vergleich(KVNr INTEGER,UKVNr INTEGER,AG INTEGER,GNR VARCHAR(7),Quartal INTEGER,Jahr INTEGER,VerglWert REAL,Anzahl REAL,Faelle REAL,Fikt INTEGER,Neu INTEGER,Arztnummer VARCHAR(10),PKey BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1,INCREMENT BY 1))

Die Datei beinhaltet INSERT INTO Statements. Diese Statements sehen alle folgendermaßen aus:
INSERT INTO Vergleich(KVNr,UKVNr,AG,GNR,Quartal,Jahr,VerglWert,Anzahl,Faelle,Fikt,Neu,Arztnummer) VALUES(1,1,14,'01100',2,2005,0.5847411,189.0,0.0,1,0,null)


Ich würde mich freuen, wenn mir jemand von euch einen Tipp geben könnte an welcher Stelle mein Denkfehler liegt.

Vielen Dank im voraus

Gruß

Paladin
 

bronks

Top Contributor
Paladin hat gesagt.:
... Derby Datenbank 200000 Zeilen und mehr einzufügen. Bis zu 10000 Zeilen funktioniert das auch in einer annehmbaren Geschwindigkeit aber alles jenseits von 50000 Zeilen dauert extrem lange. Ich hab zum Beispiel versucht 200000 Zeilen einzufügen und hab den Versuch nach etwas mehr als 10min abgebrochen weils einfach zu lange dauert.
Ich kenn Derby nicht und hab keine Ahnung was für Geschwindigkeiten Du erwartest. Mit den gängigen Datenbanken erreiche ich mit den zur Zeit schnellsten 1-CPU-IntelRechnern so ca. +- 1000 Inserts je Minute. Bei Deinen 200000 Zeilen solltest Du bei solchen Geräten knappe 4 Stunden Geduld mitbringen. Das hängt auch davon ab, wie die DB-Tabelle indiziert ist und in welcher Reihenfolge die Daten in der Textdatei stehen.
 

Paladin

Bekanntes Mitglied
Mit setAutocommit(false) ist es zwar schon schneller aber die Geschwindigkeit ist immer noch nicht akzeptabel. Vielleicht muss ich ja eine andere Datenbank benutzen?

@bronks: Es muss doch eine Möglichkeit geben Daten schneller in die DB zu bekommen. 200000 Zeilen sind ja nun auch nicht gerade sooo viel.

Gruß

Paladin
 

robertpic71

Bekanntes Mitglied
Also ich denke auch, dass die Anforderungen etwas hoch geschraubt sind. Unser bestes Pferd im Stall (DB2 auf PowerPC) schafft knapp 50.000 INSERTS pro Minute (300 Byte Satzlänge, 1 Index).

Wie AlArenal bereits geschrieben hat, ist das Autocommit ein ziemlicher Bremser. Allerdings kann eine große Transaktion für 100.000 Sätze (zumindest für laut IBM DB2 Doku) auch in schlechte Perfomance ausarten. Bei uns im Haus hat sich für Massenverarbeitung ein COMMIT alle 2000-5000 Sätze (je nach Satzlänge) eingebürgert.

Bei Tip's und Tricks zur Performance fast aller Datenbanken wird immer auf die Verwendung von PreparedStatements hingewiesen. Ein SQL-Statement muss interpretiert bzw. vorcompiliert werden. Ohne PreparedStatements werden also bei 200.000 INSERT, 200.000 Zeilen vorcompiliert.

Siehe auch: db.apache.org/derby/docs/10.0/manuals/tuning/perf34.html

LG Robert
 

Bleiglanz

Gesperrter Benutzer
Code:
INSERT INTO TwoColumnTable VALUES
    (1, 'first row'),
    (2, 'second row'),
    (3, 'third row')
zum einfügen mehrerer Zeilen verwenden (auch JDBC Batch Verarbeitung beachten...)

und probiermal

Code:
java -Djdbc.drivers=org.apache.derby.jdbc.EmbeddedDriver
    org.apache.derby.tools.ij < diedateimitdeninserts.sql
 

bronks

Top Contributor
Paladin hat gesagt.:
@bronks: Es muss doch eine Möglichkeit geben Daten schneller in die DB zu bekommen. 200000 Zeilen sind ja nun auch nicht gerade sooo viel.
Natürlich gibt es die. Du verwendest dafür leider die absolut falsche Technik. Da steckt sehr viel Aufwand dahinter von einem Client (in dem Fall Java) einen Insert an eine DB zu schicken. Zum einen hat man Netzwerkverkehr, der erstmal erzeugt werden muß. Der Client muß dem Server die Hand schütteln im sagen, was er haben will und dann das ganze rückwärts, weil der Client wissen will, ob der Server auch seine Arbeit gemacht hat. Zum anderen belastet man die Netzwerkdienste , welche auch noch ordentlich Leistung haben wollen. Große Transaktionen helfen zwar dabei diesen Aufwand zu reduzieren, sind dafür aber eigentlich nicht gedacht.

Wenn Du Dein SQL-Script direkt an den Server richtest bzw. gegen den Server ausführst, dann kannst Du damit rechnen, daß > 10000 Inserts pro Sekunde durchlaufen werden.
 

Paladin

Bekanntes Mitglied
@Bleiglanz
Wenn ich einen Datensatz nach dem von dir angegebenen Schema (INSERT INTO TwoColumnTable VALUES
(1, 'first row'),(2, 'second row'),(3, 'third row')) einfügen will bekomme ich

ERROR 42X61: Types 'INTEGER' and 'CHAR' are not UNION compatible.

von Eclipse zurück.

Ist mein Statement nicht korrekt?

Code:
INSERT INTO Vergleich VALUES (1,'KVNr'),(1,'UKVNr'),(14,'AG'),('01100','GNR'),(2,'Quartal'),(2005,'Jahr'),(0.5847411,'VerglWert'),(189.0,'Anzahl'),(0.0,'Faelle'),(1,'Fikt'),(0,'Neu'),(null,'Arztnummer')
 

Exceptionist

Aktives Mitglied
ÖÖÖÖHHHM, was hälst du denn davon eine andere Datenbank zu benutzen??
oder ist diese derby-database zwingend notwendig??

ich hab zwar nur grundlagenwissen, aber wenn du die einzutragenden werte als datei irgendwo hast, kannst du das doch auch über das datenbanksystem machen oder nicht?

also bei Oracle9i und MySQL geht das.
 

Bleiglanz

Gesperrter Benutzer
(1,'KVNr'),
(1,'UKVNr'),
(14,'AG'),
('01100','GNR'), // HÄ?? warum als erstes Arg ein Char??


die Spaltentypen müssen schon stimmen??
 

Paladin

Bekanntes Mitglied
@Bleiglanz:

Ich hab das folgendermaßen verstanden:

INSERT INTO TwoColumnTable VALUES
(Wert, 'Name1'),
(Wert, 'Name2'),
(Wert, 'Name3')

oder wie meinst du das?

@Exceptionist:
Die DerbyDB ist nicht zwingend vorgegeben. Wenns gar nicht geht wechsel ich auch
wieder zur HSQLDB. Die ist beim einfügen um einiges schneller.
 

Exceptionist

Aktives Mitglied
Ach jo, was mir grad mal einfällt...
bei dem insert- vorgang...ähhm du sprichst eine spalte nach der anderen an oder nicht??

wenn du nämlich nur in bestimmte spalten etwas eintragen möchtest, musste die spaltennamen nämlich auch angeben...
ansonsten reicht ein
insert into tabellenname
values(?,?,?,...usw)
 

Paladin

Bekanntes Mitglied
ja, ich fülle in jede spalte einen wert bei dem insert vorgang.
Ich werde das mit dem weglassen der spaltennamen mal versuchen. Bei 200000 zeilen dürfte selbst das Zeit sparen
 

KSG9|sebastian

Top Contributor
INSERT INTO TabelleABC VALUES (wert_spalte1, wert_spalte2..)

Das einzige unterschied ist, dass du nicht mit angibst, welcher Wert auf welche Spalte gemappt wird.

INSERT INTO TabellABC(a, b, c) VALUES(1, 2, 3)

gibt ja folgende Zuordnung vor:

Spalte a wird der Wert 1 zugeordnet
Spalte b wird der Wert 2 zugeordnet
Spalte c wird der Wert 3 zugeordnet


INSERT INTO TabelleABC VALUES (1, 2, 3, 4, 5)

sieht die Zuordnung so aus:

Spalte 1 wird der Wert 1 zugeordnet
Spalte 2 wird der Wert 2 zugeordnet
Spalte 3 wird der Wert 3 zugeordnet
Spalte 4 wird der Wert 4 zugeordnet
Spalte 5 wird der Wert 5 zugeordnet

Dabei musst du beachten, dass du für JEDE Spalte nen Wert mitgibst, d.h. bei ner Tabelle mit 5 Spalten musst du auch genau 5 Werte in der Klammer übergeben
 

Exceptionist

Aktives Mitglied
jupp!! mein reden, hab nur nicht die zeit, um so viel zu schreiben
*grins*

aber wenn paladin ja sowieso in jede spalte etwas eintragen möchte, ist das (wie ich denke) die sinnvollste variante...
oder etwa nicht?
 

Paladin

Bekanntes Mitglied
Das mit dem einfügen mit und ohne spaltennamen ist mir schon klar ich war nur verwirrt hat mich
das schema welches Bleiglanz beschrieben hat:

INSERT INTO TwoColumnTable VALUES
(1, 'first row'),
(2, 'second row'),
(3, 'third row')

Aber ich nehme mal an, dass er das gleiche meinte wie sebastian gerade sehr ausführlich beschrieben hat :wink:
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben