2500 Datensätze schnell in eine SQlite3 schreiben
-
- Beiträge: 478
- Registriert: Fr 13. Sep 2013, 12:07
- OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
- CPU-Target: 64Bit
- Wohnort: Rügen
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Hallo,
nun funktioniert es - CachedUpdates war noch aktiviert habe ich raus genommen und nun dauert es 0,68s für 2468 Datensätze incl Parsen aus einer ADIF Datei.
Vielen Dank an alle die mir geholfen haben !
Ich habe dank euch sehr viel gelernt!
Gruß Frank
nun funktioniert es - CachedUpdates war noch aktiviert habe ich raus genommen und nun dauert es 0,68s für 2468 Datensätze incl Parsen aus einer ADIF Datei.
Vielen Dank an alle die mir geholfen haben !
Ich habe dank euch sehr viel gelernt!
Gruß Frank
-
- Beiträge: 478
- Registriert: Fr 13. Sep 2013, 12:07
- OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
- CPU-Target: 64Bit
- Wohnort: Rügen
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Hallo,
es gibt doch noch ein Problem.
Wenn die Datenbanktabelle leer ist dann funktioniert der Import sauber.
Wenn jedoch Daten bereits vorhanden sind dann schmiert er ab.
Woran könnte es liegen ?
Gruß Frank
es gibt doch noch ein Problem.
Wenn die Datenbanktabelle leer ist dann funktioniert der Import sauber.
Wenn jedoch Daten bereits vorhanden sind dann schmiert er ab.
Woran könnte es liegen ?
Gruß Frank
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Vermutlich zweimal dieselben Daten eingelesen, dann gibt es einen Fehler im primary index -> es dürfen keine records mit identischen callsign,utc,date,band und mode Feldern existieren.
-
- Beiträge: 478
- Registriert: Fr 13. Sep 2013, 12:07
- OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
- CPU-Target: 64Bit
- Wohnort: Rügen
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Hallo mse,
genau dass war es - andere Daten hinterhergeschoben funktioniert. DANKE!
genau dass war es - andere Daten hinterhergeschoben funktioniert. DANKE!
-
- Beiträge: 6079
- Registriert: Do 21. Sep 2006, 07:51
- OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
- CPU-Target: AVR,ARM,x86(-64)
- Wohnort: Dessau
- Kontaktdaten:
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Code: Alles auswählen
SELECT * FROM log LIMIT 1;
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/
-
- Beiträge: 478
- Registriert: Fr 13. Sep 2013, 12:07
- OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
- CPU-Target: 64Bit
- Wohnort: Rügen
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
... wie kann man es sinnvoll abfangen dass das Programm nicht abschmiert wenn versucht wird gleiche Daten einzulesen ?
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Das kommt darauf an, wie du im Falle von doppelten primary keys verfahren willst.
Im erwähnten Beispiel mache ich im Fehlerfall einen "rollback" statt "commit", das heisst die ganze neue QSL-Liste wird verworfen.
https://gitlab.com/mseide-msegui/mseuni ... s/main.pas
https://gitlab.com/mseide-msegui/mseuni ... module.pas
Rollback gibt es auch in Zeos (TZConnection.Rollback) oder direkt als SQL
https://sqlite.org/lang_transaction.html
Im erwähnten Beispiel mache ich im Fehlerfall einen "rollback" statt "commit", das heisst die ganze neue QSL-Liste wird verworfen.
https://gitlab.com/mseide-msegui/mseuni ... s/main.pas
https://gitlab.com/mseide-msegui/mseuni ... module.pas
Rollback gibt es auch in Zeos (TZConnection.Rollback) oder direkt als SQL
https://sqlite.org/lang_transaction.html
-
- Beiträge: 478
- Registriert: Fr 13. Sep 2013, 12:07
- OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
- CPU-Target: 64Bit
- Wohnort: Rügen
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
...
gibt es da nicht was, das die ZQuery mäckert mit einer sinnvollen Meldung, dass man dann ein Rollback machen kann ?

gibt es da nicht was, das die ZQuery mäckert mit einer sinnvollen Meldung, dass man dann ein Rollback machen kann ?
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Vor dem Schreiben eines Records prüfen, ob er schon existiert?DL3AD hat geschrieben:... wie kann man es sinnvoll abfangen dass das Programm nicht abschmiert wenn versucht wird gleiche Daten einzulesen ?
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Fehler werden als exception gemeldet (du bezeichnest das als "abschmieren").DL3AD hat geschrieben: gibt es da nicht was, das die ZQuery mäckert mit einer sinnvollen Meldung, dass man dann ein Rollback machen kann ?
https://www.freepascal.org/docs-html/cu ... 6-24800017
Bei mir sieht es so aus: Ich fange die exception mit "except" ab, mache den rollback und werfe die exception nochmals mit "raise", damit der Nutzer davon erfährt, siehe Beispiel. Was möchtest du mit doppelten Einträgen machen?
-
- Beiträge: 478
- Registriert: Fr 13. Sep 2013, 12:07
- OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
- CPU-Target: 64Bit
- Wohnort: Rügen
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Hallo,
ich habe mal bei einem Anderen Programm (Windows auf .Net basis) welches auch den ADTF import macht angeschaut wie es reagiert wenn man Datensätze Doppelt einließt.
Es werden in einem vermutlich Memo genau die Fehlermeldungen untereinander ausgegeben wie in deinem Post zuvor gezeigt.
D.h. es wird versucht den Datensatz zu schreiben - klappt es nicht Fehlermeldung ins Memo und weiter mit dem nächsten.
Meine Struktur zum schweiben der Datensätze sieht so aus
Wie muss hier try except und raise rein um die Meldungen in einem Memo zu listen ?
Gruß Frank
ich habe mal bei einem Anderen Programm (Windows auf .Net basis) welches auch den ADTF import macht angeschaut wie es reagiert wenn man Datensätze Doppelt einließt.
Es werden in einem vermutlich Memo genau die Fehlermeldungen untereinander ausgegeben wie in deinem Post zuvor gezeigt.
D.h. es wird versucht den Datensatz zu schreiben - klappt es nicht Fehlermeldung ins Memo und weiter mit dem nächsten.
Meine Struktur zum schweiben der Datensätze sieht so aus
Code: Alles auswählen
QueryLog.SQL.Text:='BEGIN EXCLUSIVE TRANSACTION';
QueryLog.ExecSQL;
QueryLog.SQL.Text:='SELECT * FROM log LIMIT 1';
QueryLog.Open;
while (ADIFPars.Ai < Length(ADIFPars.Txt)) do//Importschleife
begin
GetRecord(ACALL,AQTH,ANAME,ATIME_ON,AQSO_DATE,ARST_SENT,ARST_RCVD,ABAND,
AFREQ,AMODE,ACONT,AITUZ,ACQZ,ADXCC,ACOUNTRY,AGRIDSQUARE,AIOTA,
ASTATE,AQSL_RCVD,ALOTW_QSL_RCVD,AEQSL_QSL_RCVD,ACOMMENT,APFX);
if ACALL <> '' then
begin
WriteDB;//Datensätze schreiben
inc(n); //QSO Zähler erhöhen
end;
end;
QueryLog.SQL.Text:='COMMIT TRANSACTION';
QueryLog.ExecSQL;
Gruß Frank
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Vermutlich rund um <TZQuery>.Post(). Wie bereits mehrmals erwähnt würde ich nicht Insert() und Post() sondern <TZReadonlyQuery>.ExecSQL() mit einem entsprechenden INSERT statement verwenden.DL3AD hat geschrieben: Wie muss hier try except und raise rein um die Meldungen in einem Memo zu listen ?
Im erweiterten Beispiel
https://gitlab.com/mseide-msegui/mseuni ... ertrecords
sieht es so aus:
Code: Alles auswählen
function tdbmo.writelogrec(const logrec: adlogrecty): boolean;
var
f1: adiftagty;
begin
result:= false;
for f1:= firstlogfield to lastlogfield do begin
fparams[f1].asnullmsestring:= logrec.fields[f1];
end;
try
insertstatement.execute();
result:= true; //im fehlerfall wird diese zeile nicht erreicht
except
on e: esqlite3error do begin
flasterror:= e.errormessage;
end;
else begin
raise; //not expected error
end;
end;
end;
Code: Alles auswählen
on e: exception do begin
flasterror:= e.message;
end;
Zur Vollständigkeit noch die Hauptroutine:
Code: Alles auswählen
procedure tmainfo.testexe(const sender: TObject);
var
rec1: adlogrecty;
t1,t2: tdatetime;
i1,i2: int32;
f1: adiftagty;
begin
for f1:= firstlogfield to lastlogfield do begin
rec1.fields[f1]:= msestring(adiftagnames[f1]);
end;
t1:= nowutc();
rec1.fields[at_qso_date]:= datetoadif(t1);
rec1.fields[at_time_on]:= timetoadif(t1);
dbmo.init();
errordisp.clear();
i2:= errored.value;
if i2 > 0 then begin
i2:= reccounted.value div i2;
end;
t1:= nowutc();
try
for i1:= 1 to reccounted.value do begin
if (i2 = 0) or (i1 mod i2 <> 0) then begin //else produce an error
rec1.fields[at_call]:= inttostrmse(i1);
end;
if not dbmo.writelogrec(rec1) then begin
errordisp.appenddatarow(dbmo.lasterror);
end;
end;
dbmo.commit();
except
dbmo.rollback();
raise;
end;
t2:= nowutc();
runtimedi.value:= (t2-t1)*24*60*60;
importcountdisp.value:= reccounted.value-errordisp.rowcount;
end;
-
- Beiträge: 478
- Registriert: Fr 13. Sep 2013, 12:07
- OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
- CPU-Target: 64Bit
- Wohnort: Rügen
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Hallo mse,
es ist ja nett das du mir helfen willst Danke dafür - aber ich sehe in deinem code nicht durch - sicherlich kann man verschiedene Dinge ander und besser machen - aber so weit bin ich noch nicht.
Ich habe extra meinen Code gepostet.
Wie muss hier try except und raise rein um die Meldungen in einem Memo zu listen ?
Gruß Frank
es ist ja nett das du mir helfen willst Danke dafür - aber ich sehe in deinem code nicht durch - sicherlich kann man verschiedene Dinge ander und besser machen - aber so weit bin ich noch nicht.
Ich habe extra meinen Code gepostet.
Wie muss hier try except und raise rein um die Meldungen in einem Memo zu listen ?
Gruß Frank
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Ich weiß nicht, was WriteDB im Detail macht (das ist das Problem mit partiell gepostetem Code), aber dort wird wahrscheinlich die Exception auftreten. Also umgibst du diesen Aufruf mit try-except und schreibst im except-Fall die Meldung ins Memo. Also so:DL3AD hat geschrieben:Wie muss hier try except und raise rein um die Meldungen in einem Memo zu listen ?Code: Alles auswählen
QueryLog.SQL.Text:='BEGIN EXCLUSIVE TRANSACTION'; QueryLog.ExecSQL; QueryLog.SQL.Text:='SELECT * FROM log LIMIT 1'; QueryLog.Open; while (ADIFPars.Ai < Length(ADIFPars.Txt)) do//Importschleife begin GetRecord(ACALL,AQTH,ANAME,ATIME_ON,AQSO_DATE,ARST_SENT,ARST_RCVD,ABAND, AFREQ,AMODE,ACONT,AITUZ,ACQZ,ADXCC,ACOUNTRY,AGRIDSQUARE,AIOTA, ASTATE,AQSL_RCVD,ALOTW_QSL_RCVD,AEQSL_QSL_RCVD,ACOMMENT,APFX); if ACALL <> '' then begin WriteDB;//Datensätze schreiben inc(n); //QSO Zähler erhöhen end; end; QueryLog.SQL.Text:='COMMIT TRANSACTION'; QueryLog.ExecSQL;
Code: Alles auswählen
while (ADIFPars.Ai < Length(ADIFPars.Txt) do begin
GetRecord(ACALL, ...);
if ACALL <> '' then
begin
try
WriteDB;
inc(n);
except
on E:Exception do Memo1.Lines.Add(E.Message);
end;
end;
QueryLog.SQL.Text := '....';
QueryLog.ExecSQL;
...
-
- Beiträge: 478
- Registriert: Fr 13. Sep 2013, 12:07
- OS, Lazarus, FPC: Debian Bullseye (L 2.2.0)
- CPU-Target: 64Bit
- Wohnort: Rügen
Re: 2500 Datensätze schnell in eine SQlite3 schreiben
Hallo wp_xyz,
vielen Dank !
Das war der passende Hinweis.
Wenn ich das richtig verstanden habe dann umschließt try und except den Programmteil der "abgesichert" werden soll
und zwischen except und dem end kommt rein was man im Fehlerfall macht ?
Wozu ist raise und finaly da ?
Gruß Frank
vielen Dank !
Das war der passende Hinweis.
Wenn ich das richtig verstanden habe dann umschließt try und except den Programmteil der "abgesichert" werden soll
und zwischen except und dem end kommt rein was man im Fehlerfall macht ?
Wozu ist raise und finaly da ?
Gruß Frank