![]() |
Datenbank: firebird • Version: 2.1 • Zugriff über: zeos
Insert Optimierung
Hallo,
Den folgenden Quelltext habe ich im Forum gefunden und für meinen Zweck angepaßt:
Delphi-Quellcode:
procedure TForm1.InputDatasetClick(Sender: TObject);
var i:Integer; startzeit,stopzeit : TDateTime; begin startzeit := now; Screen.Cursor := crHourGlass; ZConnection.Database := 'c:\msql\firedb.fdb'; for i:=0 to SG1.RowCount-1 do begin ZQuery1.SQL.text:='INSERT INTO TestTabelle (Wert1, Wert2) VALUES(:v1, :v2)'; with ZQuery1.params do begin ParamValues['v1']:=SG1.Cells[0, i]; ParamValues['v2']:=SG1.Cells[1, i]; end; // with ZQuery1.ExecSQL; end; // i Screen.Cursor := crDefault; stopzeit := now; Panel1.Caption :='SuchZeit : '+ FormatDateTime('nn:ss:zzz', StopZeit - StartZeit) ; end; Das Übertragen von ca. 35000 Datensätzen dauert ca. 4 Minuten. Kann die Übertragung beschleunigt werden? Ich habe mich natürlich über einige andere Möglichkeiten informiert. zB. Bulk insert wird aber von Firebird leider nicht unterstützt. oder external tables bei denen Sicherheitsbedenken bestehen? Welche das sind...?? daraus folgt vermutlich für mich nicht verwendbar. Ich bitte um Eure Hilfe |
AW: Insert Optimierung
Das
Delphi-Quellcode:
reicht doch einmal aus, also vor der Schleife.
ZQuery1.SQL.Text := 'INSERT INTO TestTabelle (Wert1, Wert2) VALUES(:v1, :v2)';
Und du kannst mal probieren, ob eine Zusammenfassung mehrere Werte noch ein bissl was rausholen kannst.
Delphi-Quellcode:
Mit vielen kleinen Inserts, haben wir in Postgres, mit PgDAC, etwa 60 bis maximal 250 Datensätze rausbekommen.
ZQuery1.SQL.Text := 'INSERT INTO TestTabelle (Wert1, Wert2) VALUES (:v0, :v1), (:v2, :v3), (:v4, :v5), (:v6, :v7);';
... with ZQuery1.Params do begin ParamValues[0] := SG1.Cells[0, i]; ParamValues[1] := SG1.Cells[1, i]; ParamValues[2] := SG1.Cells[0, i + 1]; ParamValues[3] := SG1.Cells[1, i + 1]; ParamValues[4] := SG1.Cells[0, i + 2]; ParamValues[5] := SG1.Cells[1, i + 2]; ParamValues[6] := SG1.Cells[0, i + 3]; ParamValues[7] := SG1.Cells[1, i + 3]; end; ZQuery1.ExecSQL; Mit deaktivierten Triggern und soeinem zusammengefassten Insert sind wir schon auf über 600 DS/s gekommen. Das liegt aber irgendwie am Delphi, denn in C# soll es wesentlich schneller gehn ... ich glaub da was von über 10.000 DS/s gehört zu haben. Wenn dei DBMS sowas wie einen COPY-Befehl kennt, worüber man z.B. die Daten via einer CSV-Datei direkt in die Datenbank reinbekommt, dann wäre das wohl der schnellste Weg. |
AW: Insert Optimierung
Du schleppst 35.000 datensätze in einem Stringgrid mit Dir herum?
Wie wäre es dafür eine Stringlist oder eine List zu nehmen? Ein Stringgrid ist ja eigentlich für die Datenanzeige zuständig, nicht für die Datenhaltung. Da sollte noch etwas für Dich drin sein. Gruß K-H |
AW: Insert Optimierung
Nunja, in einem TStringGrid stecken auch nur ein paar TStringLists.
Oder wie wäre es mit einem Memory-DataSet und einem DBGrid? |
AW: Insert Optimierung
...ausserdem solltest Du den Query Text vor dem For setzen und mit Prepare der Datenbank die Chance geben dieses Statement vorzubereiten. In der Schleife setzt du nur noch die Parameter. Das bringt dann einiges an Speed.
|
AW: Insert Optimierung
Zitat:
richtig!! egal wo INSERT steht,ausgeführt wird es mit execsql.
Delphi-Quellcode:
Genau das ist meines Verständnisses nach Bulk insert?
ZQuery1.SQL.Text := 'INSERT INTO TestTabelle (Wert1, Wert2) VALUES (:v0, :v1), (:v2, :v3), (:v4, :v5), (:v6, :v7);';
... with ZQuery1.Params do begin ParamValues[0] := SG1.Cells[0, i]; ParamValues[1] := SG1.Cells[1, i]; ParamValues[2] := SG1.Cells[0, i + 1]; ParamValues[3] := SG1.Cells[1, i + 1]; ParamValues[4] := SG1.Cells[0, i + 2]; ParamValues[5] := SG1.Cells[1, i + 2]; ParamValues[6] := SG1.Cells[0, i + 3]; ParamValues[7] := SG1.Cells[1, i + 3]; end; ZQuery1.ExecSQL; Packe eine Reihe Parameter in einen Bulk (=Paket) und überführe mit einem Insert das Paket. Zitat:
Stringlist hätte ich auch gern genommen, aber meine Programmierkenntnisse reichen dafür nicht aus. Zitat:
|
AW: Insert Optimierung
Hallo,
hat die Testtabelle irgendwelche Indizes ? Die könnte man vor dem Insert deaktivieren. Mit dem ZEOS und Prepare ist in der Tat so, er prepared selber, allerdings darf sich der SQL-Text nicht ändern, was hier durch Nutzung von Parametern ja auch gut gemacht wird. Heiko |
AW: Insert Optimierung
Den ZQuery.text vor die Schleife zu ziehen, statt in der Schleife zu haben, wie in Post 1 bringt sage und schreibe rund 30 sec.
Jetzt habe ich die Parameterliste eingefügt und es passiert absolut nichts. Zeitmessung zeigt 0,00 Wo ist der Fehler?
Delphi-Quellcode:
Indizes existieren nicht,
var i:Integer;
var startzeit,stopzeit : TDateTime; begin startzeit := now; Screen.Cursor := crHourGlass; ZConnection.Database := 'c:\msql\firedb.fdb'; Zquery1.SQL.Text:='INSERT INTO TestTabelle (Wert1, Wert2) VALUES(:v1, :v2), (:v3, :v4), (:v5, :v6), (:v7, :v8), (:v9, :v10)'; while i <= SG1.RowCount-1 do begin with ZQuery1.params do begin ParamValues['v1']:=SG1.Cells[0, i]; ParamValues['v2']:=SG1.Cells[1, i]; ParamValues['v3'] := SG1.Cells[0, i + 1]; ParamValues['v4'] := SG1.Cells[1, i + 1]; ParamValues['v5'] := SG1.Cells[0, i + 2]; ParamValues['v6'] := SG1.Cells[1, i + 2]; ParamValues['v7'] := SG1.Cells[0, i + 3]; ParamValues['v8'] := SG1.Cells[1, i + 3]; ParamValues['v9'] := SG1.Cells[0, i + 4]; ParamValues['v10']:= SG1.Cells[1, i + 4]; end; // with ZQuery1.ExecSQL; i := i+5; end; // i Screen.Cursor := crDefault; stopzeit := now; Panel1.Caption :='SuchZeit : '+ FormatDateTime('nn:ss:zzz', StopZeit - StartZeit) ; end; Trigger (was auch immer das ist) auch nicht. |
AW: Insert Optimierung
Jupp, eine Schleife mit dem zusammengefassten Statement und größeren Schritten
Der Vorteil an dem indizierten Indize und nicht den Namentlichen wäre, daß man eine innere Schleife befüllen könnte und so z.B. 100 Werte zusammenfassen könnte. (müßte man mal ausprobieren, welche Größe halbwegs optimal ist) und zum Schluß nicht vergessen, daß da noch ein paar Zeilen übrigbleiben können. Entweder man bastelt das Insert-Statement als String zusammen, für die Restlichen und vorher einmal für alle Teile oder man läßt den Rest über ein einfaches Insert, mit je einem der Restwerte, übertragen. |
AW: Insert Optimierung
Viel schneller geht es, wenn Du die Daten in eine Textdatei packst und dann per
![]() Wenn Du unbedingt mit INSERT-Befehlen arbeiten musst, dann könnte es viel schneller sein, wenn Du dir das Skript zunächst in einer Stringliste zusammenbaust und dann als ein Befehl innerhalb einer Transaktion ausführen lässt. Zitat:
|
AW: Insert Optimierung
Beim Bulk-Insert mußt du aber aufpassen.
Klient und Datenbankserver müssen auf die selben Speicherplätze zugreifen und sollten womöglich auch noch über die selben Netzwerkadressen verfügen (abgesehn man nutzt im Klient einen Dateipfad, und gibt dann dem Server einen anderen Pfad mit, unter welchem er die Datei findet) Bei ![]() |
AW: Insert Optimierung
Zitat:
|
AW: Insert Optimierung
Delphi-Quellcode:
Das Problem dabei: Wo vorher keine Fehlermeldung war, erscheint jetzt
var i:Integer;
var startzeit,stopzeit : TDateTime; begin startzeit := now; i := 0; // Initialisierung von i Screen.Cursor := crHourGlass; ZConnection.Database := 'c:\msql\firedb.fdb'; Zquery1.SQL.Text:='INSERT INTO TestTabelle (Wert1, Wert2) VALUES(:v1, :v2), (:v3, :v4), (:v5, :v6), (:v7, :v8), (:v9, :v10)'; while i <= SG1.RowCount-1 do begin with ZQuery1.params do begin ParamValues['v1']:=SG1.Cells[0, i]; ParamValues['v2']:=SG1.Cells[1, i]; ParamValues['v3'] := SG1.Cells[0, i + 1]; ParamValues['v4'] := SG1.Cells[1, i + 1]; ParamValues['v5'] := SG1.Cells[0, i + 2]; ParamValues['v6'] := SG1.Cells[1, i + 2]; ParamValues['v7'] := SG1.Cells[0, i + 3]; ParamValues['v8'] := SG1.Cells[1, i + 3]; ParamValues['v9'] := SG1.Cells[0, i + 4]; ParamValues['v10']:= SG1.Cells[1, i + 4]; end; // with ZQuery1.ExecSQL; i := i+5; end; // i Screen.Cursor := crDefault; stopzeit := now; Panel1.Caption :='SuchZeit : '+ FormatDateTime('nn:ss:zzz', StopZeit - StartZeit) ; end;
Code:
Spalte 51?? Es gibt nur 2 Spalten.
Benachrichtigung über Debugger-Exception
--------------------------- Im Projekt Project2.exe ist eine Exception der Klasse EZSQLException aufgetreten. Meldung: 'SQL Error: Dynamic SQL Error SQL error code = -104 Token unknown - line 1, column 51 ,. Error Code: -104. Invalid token The SQL: INSERT INTO Testtabelle (Wert1, Wert2) VALUES(?, ?), (?, ?), (?, ?), (?, ?), (?, ?); '. Prozeß wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen. --------------------------- OK Hilfe --------------------------- Bitte um Übersetzung dieser Fehlermeldung. @ Furtbichler @ Himitsu bulk insert Erkläre mir einer diesen Begriff. Ich meine gelesen zu haben, daß bulk insert bei Firebird nicht möglich ist. Der Link von Furtbichler verweist auf externalTables. Um dies nutzen zu können, muß ich doch mir unbekannte Veränderungen an der firebird.conf Datei vornehmen!?? Zitat:
|
AW: Insert Optimierung
Joar, wenn dann noch die Zugriffsrechte auf das Verzeichnis passend sind.
Bei uns auf'm Server hab ich ein privates virtuelles SUBST-Laufwerk, wo meine Verzeichnisse reingemappt sind ... der SQL-Server hat auf diese nicht direkt Zugriff drauf, auf dieses Arbeits-Laufwerk, außer über den originalen Pfad. Nicht Spalte 51, sondern Zeichen 51. Das ist auf den SQL-Text bezogen > Zeile und Spalte/Zeichen/Buchstabe. Die schließende Klammer ) nach dem ersten Wertepaar? :gruebel: [edit] Oder das Komma danach? :gruebel: ![]() Eventuell kann Firebird das nicht? :shock: Vielleicht dann einfach so. (Das andere wäre halt kürzer)
SQL-Code:
Es geht ja einfach nur darum, den Traffik und die Anzahl der Anfragen an den Server zu verringern.
INSERT INTO Testtabelle (Wert1, Wert2) VALUES (?, ?);
INSERT INTO Testtabelle (Wert1, Wert2) VALUES (?, ?); INSERT INTO Testtabelle (Wert1, Wert2) VALUES (?, ?); INSERT INTO Testtabelle (Wert1, Wert2) VALUES (?, ?); INSERT INTO Testtabelle (Wert1, Wert2) VALUES (?, ?); |
AW: Insert Optimierung
So etwa??
Delphi-Quellcode:
Kompilierung einwandfrei
procedure TForm1.InputDataset3Click(Sender: TObject);
var i:Integer; var startzeit,stopzeit : TDateTime; begin i := 0; startzeit := now; Screen.Cursor := crHourGlass; ZConnection.Database := 'c:\msql\firedb.fdb'; Zquery1.SQL.Text:='INSERT INTO Testtabelle (Wert1, Wert2) VALUES(:v1, :v2)'; Zquery1.SQL.Text:='INSERT INTO Testtabelle (Wert1, Wert2) VALUES(:v3, :v4)'; Zquery1.SQL.Text:='INSERT INTO Testtabelle (Wert1, Wert2) VALUES(:v5, :v6)'; Zquery1.SQL.Text:='INSERT INTO Testtabelle (Wert1, Wert2) VALUES(:v7, :v8)'; Zquery1.SQL.Text:='INSERT INTO Testtabelle (Wert1, Wert2) VALUES(:v9, :v10)'; while i <= SG1.RowCount-1 do begin with ZQuery1.params do begin ParamValues['v1']:=SG1.Cells[0, i]; ParamValues['v2']:=SG1.Cells[1, i]; ParamValues['v3'] := SG1.Cells[0, i + 1]; ParamValues['v4'] := SG1.Cells[1, i + 1]; ParamValues['v5'] := SG1.Cells[0, i + 2]; ParamValues['v6'] := SG1.Cells[1, i + 2]; ParamValues['v7'] := SG1.Cells[0, i + 3]; ParamValues['v8'] := SG1.Cells[1, i + 3]; ParamValues['v9'] := SG1.Cells[0, i + 4]; ParamValues['v10']:= SG1.Cells[1, i + 4]; end; // with ZQuery1.ExecSQL; i := i+5; end; // i Screen.Cursor := crDefault; stopzeit := now; Panel1.Caption :='SuchZeit : '+ FormatDateTime('nn:ss:zzz', StopZeit - StartZeit) ; end; Bei Ausführung: Kann Parameter v1 nicht finden oder müssen die jeweiligen Parameter hinter dem jeweiligen insert Befehl stehen, aber nein, denn dann stehen die insert Befehle ja innerhalb der while Schleife, in welcher sie ja nichts zu suchen haben (siehe Beitrag 8) |
AW: Insert Optimierung
Du überschreibst ja auch immer wieder die Werte komplett, es gilt also immer nur die letzte Zuweiseung. :zwinker:
Fällt aber bestimmt auf, wen man mal nachsieht/debuggt, was für eine Query letzendlich ausgeführt wird. :angle2:
Delphi-Quellcode:
(die letzen beiden Queries lassen sich auch sehrt schön automatisch generieren)
ZQuery1.SQL.Text :=
'INSERT INTO dat12006 (Begriff, Frage) VALUES(:v1, :v2);'#10 + 'INSERT INTO dat12006 (Begriff, Frage) VALUES(:v3, :v4);'#10 + 'INSERT INTO dat12006 (Begriff, Frage) VALUES(:v7, :v6);'#10 + 'INSERT INTO dat12006 (Begriff, Frage) VALUES(:v7, :v8);'#10 + 'INSERT INTO dat12006 (Begriff, Frage) VALUES(:v9, :v10);'; ZQuery1.SQL.Clear; ZQuery1.SQL.Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v1, :v2);'; ZQuery1.SQL.Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v3, :v4);'; ZQuery1.SQL.Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v7, :v6);'; ZQuery1.SQL.Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v7, :v8);'; ZQuery1.SQL.Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v9, :v10);'; with ZQuery1.SQL do begin Clear; Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v1, :v2);'; Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v3, :v4);'; Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v7, :v6);'; Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v7, :v8);'; Add('INSERT INTO dat12006 (Begriff, Frage) VALUES(:v9, :v10);'; end; |
AW: Insert Optimierung
Wobei eine parametrisierte Anweisung schneller sein sollte als eine Skript mit der wiederholten Anweisung.
Bulk-Insert könnte man auch mit Hilfe einer externen Tabelle (Textdatei) versuchen. |
AW: Insert Optimierung
Man kann es kaum glauben, aber Programmieren hat tatsächlich etwas mit Mathematik zu tun.
Und wie schonmal erwähnt, fehlt noch der Rest.
Delphi-Quellcode:
PS: Mit einer ordentlichen Einrückung braucht man kaum noch kommentare, um die Zusammenhänge zu erkennen. (wie z.B. wozu das END gehört)
procedure TForm1.InputDataset3Click(Sender: TObject);
const Anzahl = 30; var StartZeit, StopZeit: TDateTime; i, i2: Integer; begin StartZeit := Now; Screen.Cursor := crHourGlass; ZConnection.Database := 'c:\msql\firedb.fdb'; ZQuery1.SQL.Clear; for i2 := 0 to Anzahl - 1 do ZQuery1.SQL.Add(Format('INSERT INTO dat12006 (Begriff, Frage) VALUES (:v%d, :v%d);', [i2 * 2, i2 * 2 + 1])); for i := 0 to SG1.RowCount div Anzahl - 1 do begin for i2 := 0 to Anzahl - 1 do begin ZQuery1.Params[i2 * 2 + 0].Value := SG1.Cells[0, i * Anzahl + i2]; ZQuery1.Params[i2 * 2 + 1].Value := SG1.Cells[1, i * Anzahl + i2]; end; ZQuery1.ExecSQL; end; //ZQuery1.SQL.Text := 'INSERT INTO dat12006 (Begriff, Frage) VALUES (:v0, :v1);'; //for i := SG1.RowCount div Anzahl * Anzahl to SG1.RowCount - 1 do begin // ZQuery1.Params[0].Value := SG1.Cells[0, i]; // ZQuery1.Params[1].Value := SG1.Cells[1, i]; // ZQuery1.ExecSQL; //end; if SG1.RowCount mod Anzahl > 0 then begin ZQuery1.SQL.Clear; for i2 := 0 to SG1.RowCount mod Anzahl - 1 do ZQuery1.SQL.Add(Format('INSERT INTO dat12006 (Begriff, Frage) VALUES (:v%d, :v%d);', [i2 * 2, i2 * 2 + 1])); i := SG1.RowCount div Anzahl; for i2 := 0 to SG1.RowCount mod Anzahl - 1 do begin ZQuery1.Params[i2 * 2 + 0].Value := SG1.Cells[0, i * Anzahl + i2]; ZQuery1.Params[i2 * 2 + 1].Value := SG1.Cells[1, i * Anzahl + i2]; end; ZQuery1.ExecSQL; end; Screen.Cursor := crDefault; StopZeit := Now; Panel1.Caption :='SuchZeit : ' + FormatDateTime('nn:ss:zzz', StopZeit - StartZeit) ; end; |
AW: Insert Optimierung
@ himitsu
Ich bedanke mich erst einmal für deine Hilfe, leider liefert die Einspielung deines Quelltextes folgende Fehlermeldung:
Code:
Spalte 54 weist auf
---------------------------
Benachrichtigung über Debugger-Exception --------------------------- Im Projekt Project2.exe ist eine Exception der Klasse EZSQLException aufgetreten. Meldung: 'SQL Error: Dynamic SQL Error SQL error code = -104 Token unknown - line 1, column 54 INSERT. Error Code: -104. Invalid token The SQL: INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?); INSERT INTO dat12006 (Begriff, Frage) VALUES (?, ?);; '. Prozeß wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen. --------------------------- OK Hilfe ---------------------------
Code:
hin. Ich habe viel zuwenig Ahnung von SQL um mit Sicherheit sagen zu können, daß es an dem fehlenden Parameter v liegt ??
VALUES (:v%d, :v%d);'
Code:
ZQuery1.Params[i2 * 2 + 0].Value := SG1.Cells[0, i * Anzahl + i2];
|
AW: Insert Optimierung
An V vollte es nicht liegen.
Man kann entweder über den Namen den Wert eines Parameters setzen, oder über den Index. (der erste Parameter im Statemant hat den Index 0) Das ist also alles das Selbe, nur das nach einem Index nicht erst gesucht werden muß:
Delphi-Quellcode:
ExecSQL sollte doch mehrere SQL-Statements verarbeiten können? :gruebel:
SQLQuery1.Params[0].Value
SQLQuery1.Params.Items[0].Value SQLQuery1.Params.ParamByName('Name des ersten Parameters').Value SQLQuery1.Params.ParamValues['Name des ersten Parameters'] Mal aus Interesse: Was passiert denn bei
Delphi-Quellcode:
?
Anzahl = 1;
|
AW: Insert Optimierung
Bei Anzahl 30 werden 30 Insertbefehle in einem Rutsch ausgeführt (siehe Fehlermeldung 30x insert). Bei Anzahl 1 demzufolge nur 1 Insert.
|
AW: Insert Optimierung
Schon klar.
Ich meinte in Bezug auf das Funktionieren, bzw. die Fehlermeldung. :stupid: |
AW: Insert Optimierung
Zitat:
|
AW: Insert Optimierung
Mit der 30 ist es doch in einer Exception geendet.
Passiert das auch mit einer 1, bei diesem Code? |
AW: Insert Optimierung
bei Anzahl = 1 : keine Fehlermeldung, Die Tabelle wird erstellt.
Schon bei Anzahl = 2 : obige Fehlermeldung (nur stark verkürzt 2 Einträge). Keine Erstellung der Tabelle. |
AW: Insert Optimierung
Ein TZQuery kann aber nur einfache Statements ausführen und kein Skript. Dafür gibt es TZSqlProcessor
|
AW: Insert Optimierung
Ich dachte Firebird kennt die meisten SQL-Features. :gruebel:
Und irgendwie muß man doch mehrere SQL-Befehle zusammen abschicken können? Eventuell noch INSERT SELECT UNION SELECT ... ![]() oder eine anonyme Funktion/Block drumrum. [edit] Oh, wo kommt denn mkinzler's Antwort her? :shock: Der TZSqlProcessor schickt das zusammen ab, oder zerlegt und versendet er das einzeln? |
AW: Insert Optimierung
Zitat:
2er Gedanke: gibt's Literatur, Anwendungsbeispiele etc. |
AW: Insert Optimierung
|
AW: Insert Optimierung
kleiner Tip:
wenn es wirklich um gleichartige einfache inserts geht, dann sparst du eine Menge zeit über execute block d.h.statt jedes insert statement mit execute/execsql senden stellt du dir deine inserts in einem Block zusammen.
Code:
das kannst du dann mit den meisten t*query oder T*sql Komponenten als ein Befehl
execute block
as begin insert into tbl(id,txt) values (1,'A'); insert into tbl(id,txt) values (2,'B'); insert into tbl(id,txt) values (3,'C'); --... insert into tbl(id,txt) values (26,'Z'); end mit execsql zum Server senden. So einen Block kann bis zu 32k lang sein, d.h. es passen reichlich inserts in einen Befehl. Über external files zu gehen ist zwar noch schneller, aber setzt voraus, das dein Firebird Client und der Firebird Server auf einen gemeinsamen Festplattenbereich zugreifen können, das ist nicht immer gewünscht. Ab einer gewissen Anzahl parametern ist die Parametrisierung von statements eher langsamer als schneller, und man sollte wissen, das bei o.a. Verfahren ca. 10 Datenpakete auf TCP/IP Ebene zwischen Server und Client hin und her geschickt werden, bei 26 Einzelstatements kommst du parametrisiert auf geschätzt mindestens 200 Datenpakete. Bei jedem Datenpaket musst du immer die Latenzzeit mit einrechnen (wie lange braucht ein Ping). Je mehr Records und je mehr Parameter, um so mehr lohnt sich das execute block verfahren! Execute block ist seit Firebird 2 Standard und hat nichts mit execute ibeblock zu tun, was man nur in IBExpert Tools nutzen kann. |
AW: Insert Optimierung
Zitat:
Wie wird dann ein solcher Block in Delphi eingebunden? |
AW: Insert Optimierung
Ist doch praktisch sowas ähliches, wie mehrere Inserts zusammen, nur in einem anonymen Block verpackt.
Von der Größe des SQL-Statements her könntest du ja nochmal Folgendes probieren, mit der nun neu bekannten SQL-Komponente.
Code:
Und wenn die Übertragung der Parameter soviel frißt, bei der Übertagung, dann könnte man ja auch nochmal versuchen keine Parameter zu nutzen.
insert into tbl(id,txt) values (1,'A'), (1,'A'), (1,'A'), (1,'A');
Aber ob sich das wirklich positiv auswirkt, müßte man mal sehn ... schließlich muß man dann die Parameter selber "ordnungsgemäß" behandeln und das SQL-Statement muß jedesmal neu zusammengebaut und vorallem erneut geparst werden. |
AW: Insert Optimierung
Also ich habe große Schwierigkeiten mir 35000 und mehr Insert befehle in einem Block vorzustellen.
Kann mir zum Thema execute Block jemand Einführungsliteratur nennen? |
AW: Insert Optimierung
Ein execute block ist eine SP, die inline deklariert wird. Es ist also SQL/PL möglich. Bei einfachen Inserts sollte aber eine normale parametrisierte Insert-Abfrage ausreichen. Auch hier kannst du die Commits blockweise ausfügren.
|
AW: Insert Optimierung
Zitat:
inline ist ??? SQL/PL heißt ??? Warum müssen die Antworten komplizierter sein als die Fragen, welche man versucht zu stellen. Ich weiß ich bin Anfänger und sollte mich um die Grundlagen selber kümmern. Dennoch, wozu ist das Forum da, wenn es keine Anfänger gäbe, sondern nur Fachleute? |
AW: Insert Optimierung
Hallo,
als Anfänger solltest du ja erst einmal anfangen, statt sich gleich an die Optimierung zu setzen. Was ist an 4 min Laufzeit sooo schlimm, dieses Insert wird doch wohl nicht zu den Haupt-Aufgaben deines Programms gehören. Mach doch erst mal so weiter. Noch was zum Probieren
Delphi-Quellcode:
Was du leider immer noch nicht geschrieben hattest:
procedure TForm1.InputDatasetClick(Sender: TObject);
var i:Integer; startzeit,stopzeit : TDateTime; begin startzeit := now; Screen.Cursor := crHourGlass; ZConnection.Database := 'c:\msql\firedb.fdb'; ZQuery1.SQL.text:='INSERT INTO TestTabelle (Wert1, Wert2) VALUES(:v1, :v2)'; ZQuery1.Prepare; for i:=0 to SG1.RowCount-1 do begin with ZQuery1.params do begin ParamValues['v1']:=SG1.Cells[0, i]; ParamValues['v2']:=SG1.Cells[1, i]; end; // with ZQuery1.ExecSQL; end; // i Screen.Cursor := crDefault; stopzeit := now; Panel1.Caption :='SuchZeit : '+ FormatDateTime('nn:ss:zzz', StopZeit - StartZeit) ; end; Hat deine Tabelle Indizes ? Heiko |
AW: Insert Optimierung
Zitat:
Zitat:
Zitat:
![]() |
AW: Insert Optimierung
@ mkinzler
Danke. @ Hoika Die Tabelle hat weder Indizes noch Trigger. Zu dem Quelltext: ZeosQuery (habe ich gelesen) besitzt die einstellbare Prepare Funktion nicht, da diese Funktion im Quelltext von Zeos bereits fest einprogrammiert ist. Mein erster Schritt: create DB, zweiter Schritt: create tabelle, dritter Schritt: bring meine Daten in die Tabelle(möglichst schnell). |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:02 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