![]() |
Datenbank: Firebird • Version: 2.1 • Zugriff über: Zeos
Insert optimieren
Moin Dp
Ich hab folgendes Problem, ich hab hier ein Array mit 4*30000 Werten, und muss dass möglichst schnell in die Firebird Datenbank einspeisen. Momentan brauch ich für die 30k werte ungefähr 30 Sekunden (übers Netzwerk), und da dachte ich mir das kann man bestimmt noch optimieren, hier mal mein Code:
Delphi-Quellcode:
Im Zquery2.Sql steht:
Frm_Messung.ZConnection1.StartTransaction;
with Frm_Messung.ZQuery2 do begin saving := true; for zt := 0 to round(Frm_Messung.Ch_Messung.BottomAxis.Maximum) do begin Params[0].AsInteger := tId; Params[1].AsInteger := zt; Params[2].AsFloat := arr_messwerte[tdim, zt, 0]; Params[3].AsFloat := arr_messwerte[tdim, zt, 1]; ExecSQL; frm_messung.pb_db.Position := frm_messung.pb_db.Position +1; end; end; (*try Frm_Messung.ZQuery2.ExecSQL; except Frm_Messung.ZConnection1.Rollback; end;*) Frm_Messung.ZConnection1.Commit;
Code:
wobei ich die Parameter alle im Query selber schon eingetragen hab.
INSERT INTO Messwerte (ID_mess, Millisec, Messwert_Links, Messwert_Rechts, Winkel, Merker) VALUES (:id, :sec, :mel, :mer, :win, :mek);
Die Parameter win und mek sind noch nicht belegt kommt aber später noch. Nun wäre halt die frage wo ich noch das eine oder andere Rädchen drehen könnte um das zu optimieren. |
AW: Insert optimieren
Normalerweise muss man am Anfang ein Prepare aufrufen damit auch wirklich das prepared statement verwendet wird. Evtl. macht das ZEOS automatisch.
Sonst könntest du versuchen mehrer inserts in einem ExecSQL abschicken (BULK INSERT). |
AW: Insert optimieren
Ich hab versucht erst nach dem for to das ExecSQL abzuschicken, dann wird _nur_ der letzte Wert eingetragen.
Wie ruf ich den das Prepare auf? |
AW: Insert optimieren
normalerweise gibts ein Property Prepared das du auf True setzt oder eine entsprechende Methode.
Aber ich weis nicht wie das Zeos bereit stellt. Beim MS SQL Server würde ich sagen: Schau doch mal im Profiler nach was auf der DB ankommt. |
AW: Insert optimieren
Also eine Option prepared hab ich nicht gefunden, weder in der Connection noch im query
|
AW: Insert optimieren
Klappt denn dies?
Delphi-Quellcode:
Frm_Messung.ZQuery2.Prepare;
|
AW: Insert optimieren
Nein es kommt die typische Meldung, TZQuery enthält kein Element namens Prepare.
|
AW: Insert optimieren
Es gibt folgende "Tricks" für schnellere Masseninsert:
1.) INSERT-Anweisung mit mehreren Zeilen
SQL-Code:
Somit kann man auf einen Rutsch einige Hundert bis Tausend Datensätze einfügen.
INSERT INTO Tabelle(KFZ, leistung)
VALUES('BMW M3', 321.0) VALUES('VW Golf5 TDI', 120.0) VALUES('Audi A3 TDI', 120.0) ... Der Vorteil ergibt sich auch dadurch, dass nicht jeder einzelne Datensatz einen TCP/IP Roundtrip erfordert. Leider verstehen nur wenige Datenbanken diese erweiterte Syntax. 2.) viele Insert-Anweisungen (getrennt durch ;) auf einen Rutsch an den Server senden. Dazu werden die Insert-Anweisung in einer Stringliste gesammelt und als ein Gesamtstring an die ExecSQL() Funktion weitergegeben. Auch hier hängt es davon ab, ob die Datenbank diesen "Batch-Betrieb" akzeptiert. In beiden Fällen müssen die Insert-Anweisung ohne Unterstützung durch Parameter erzeugt werden. Aber die höhere Einfügegeschw. sollte diesen Nachteil aufwiegen. |
AW: Insert optimieren
Zitat:
Auf was für einer Maschine läuft der Firebird? Welche Auslastung erzeugt er bei den inserts? Welche Netzlast liegt vor? Hat die Tabelle Trigger und wenn ja was tun die? Hat die Tabelle Indexe und wenn ja wie komplex sind die? Falls der FB auf einer Windows Maschine läuft: Lasse den Job doch mal auf der gleichen Maschine laufen. |
AW: Insert optimieren
Also ich hab jetzt mal den Code so abgeändert:
Delphi-Quellcode:
Dann bekomm ich immer
Frm_Messung.ZConnection1.StartTransaction;
with Frm_Messung.ZQuery2 do begin saving := true; //list.Text := 'execute block as begin'; for zt := 0 to round(Frm_Messung.Ch_Messung.BottomAxis.Maximum) do begin (*Params[0].AsInteger := tId; Params[1].AsInteger := zt; Params[2].AsFloat := arr_messwerte[tdim, zt, 0]; Params[3].AsFloat := arr_messwerte[tdim, zt, 1]; ExecSQL;*) list.Add('INSERT INTO Messwerte (ID_mess, Millisec, Messwert_Links, Messwert_Rechts) VALUES (' + InttoStr(tid) + ', ' + InttoStr(zt) +', ' + FloattoStr(arr_messwerte[tdim, zt, 0]) + ', '+ FloattoStr(arr_messwerte[tdim, zt, 1]) + ' );'); frm_messung.pb_db.Position := frm_messung.pb_db.Position +1; end; //list.Add('end'); SQL := list; end; try Frm_Messung.ZQuery2.ExecSQL; except Frm_Messung.ZConnection1.Rollback; end; Frm_Messung.ZConnection1.Commit;
Code:
@exilant
Unknown Token in Line 2 Insert
Der Firebird läuft auf einem WIN 2003 SBS, keine trigger keine indizes, und wenn ich die ganze Sache Embedded mach gehts etwas schneller so cs 15-20 sekunden für 30k Edit: Hab das grad gefunden ![]() der schafft in 19s 100k, aber ich versteh nicht ganz was er macht? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz