Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Anfängerfrage zu SQL-Insert (https://www.delphipraxis.net/207103-anfaengerfrage-zu-sql-insert.html)

Marco Steinebach 24. Feb 2021 19:21

Datenbank: Firebird • Version: 2.5 • Zugriff über: ADO und ODBC

Anfängerfrage zu SQL-Insert
 
Hallo zusammen,
Blöde DB-Anfängerfrage.
Mit folgendem Code möchte ich meine Datenbank füllen, ca. 2000 Datensätze, knapp 30 Spalten.
Code:
adoConnection1.loginprompt := false;
adoConnection1.connectionString := 'bla';
adoConnection1.connected := true;
adoCommand1.connection := adoConnection1;
for i := 0 to 2000 do
begin
  adoCommand1.commandText := 'insert into bla values (1, 2, 3);';
adoCommand1.execute;
end;
adoConnection1.connecgted := false;
Funktioniert super, braucht aber leider rund 20 Minuten. ;-) Ich schätze mal, das geht schneller, nur wie?
Ich denke, da er, bei meinem Code, jedesmal eine neue Transaktion startet dauert das so ewig lange.

Für einen Schups wäre ich sehr dankbar.

Herzlich grüßt
Marco

IBExpert 24. Feb 2021 19:39

AW: Anfängerfrage zu SQL-Insert
 
ich hab nie freiwillig mit ado gearbeitet, aber 20 minuten ist ja gruselig, ich würde 20 sekunden
schon hinterfragen.

daher

sidn irgendwelche trigger auf deiner tabelle? wenn ja, schalte die ggf mal ab
oder zeig mal die metadaten der datenbank für diese tabelle
(in ibexpert zB das was im ddl reiter zu sehen ist)

20 minuten lassen sich auch durch extra transaktionen nicht erklären, aber ggf such mal
ob die adoConnection1. irgendwas hat wie adoConnection1.starttransaction
oder adoConnection1.commit oder adoConnection1.transaction ....

ggf kannst du auch mal auf dem firebird server einen ibexpert benchmark
laufen lassen, https://www.ibexpert.com/benchmark

wenn da was auf dem system der grund sein sollte, warum firebird da so lahm
ist wirst du das auf dem weg merken

knuut21 24. Feb 2021 20:28

AW: Anfängerfrage zu SQL-Insert
 
Ich könnte mir vorstellen, dass dein Beispiel implizit eine Transaktion startet und nach dem Insert implizit ein commit ausgeführt wird. Wenn du vor der Schliefe eine Transaktion explizit startest und am Ende der Schleife die Transaktion comittest, sollte es deutlich schneller gehen.

BG

Marco Steinebach 24. Feb 2021 21:49

AW: Anfängerfrage zu SQL-Insert
 
Huhu,
Hab ich auch schon gedacht, es gibt zwar ein BeginTrans und CommitTrans, aber da ändert sich nix.
Wenn ich die Source richtig gelesen habe, interessiert das AdoCommand auch nicht wirklich...

Herzlich grüßt
Moo

Union 24. Feb 2021 22:30

AW: Anfängerfrage zu SQL-Insert
 
Ich hab mal eine Messuung vorgenommen, das sind 201 ms bei mir. Verbindung über ODBC mit ADO.
Delphi-Quellcode:
object ADOConnection1: TADOConnection
  ConnectionString =
    'Provider=MSDASQL.1;Password=masterkey;Persist Security Info=True' +
    ';User ID=SYSDBA;Data Source=Firebird Test'
  LoginPrompt = False
  Provider = 'MSDASQL.1'
end
Delphi-Quellcode:
var
  I : Integer;
  Sw : TStopWatch;
begin
  adoConnection1.connected := true;
  adoCommand1.connection := adoConnection1;

  adoCommand1.commandText := 'create table bla (one integer, two integer, three integer)';
  adoCommand1.execute;
  Sw.Start;
  for i := 0 to 2000 do
  begin
    adoCommand1.commandText := 'insert into bla values (1, 2, 3);';
    adoCommand1.execute;
  end;
  Sw.Stop;
  ShowMessageFmt('Dauer %d ms', [Sw.Elapsed.Milliseconds]);

  adoCommand1.commandText := 'drop table bla';
  adoCommand1.execute;
end;
Bei vielen nicht korrekt abgeschlossenen Transkationen (z.b. killen des Prozesses beim Debgging) macht Firebird generell schwerste Probleme. Ich hatte gerade letzte Woche den Fall, dass ein Datenimport (640.000 Inserts mit 19 Feldern) anstelle von bisher 5 Minuten 6 Stunden benötigte.

Nach Backup + Restore war alles wieder schnell wie bisher.

Jasocul 25. Feb 2021 06:46

AW: Anfängerfrage zu SQL-Insert
 
Bist du sicher, dass der Flaschenhals beim Insert ist?
Du hast den Source teilweise manuell eingetippt. So wie er da steht, würde er nicht mal compiliert. Wir wissen auch nicht, wie du die Datensätze für das Insert zusammen stellst. Auch da kann ein Flaschenhals sein.

Hat deine Zieltabelle vielleicht viele Indexe oder Constraints?
Liegt die Datenbank bei dir lokal oder ist die auf einem anderen Rechner/Server oder sogar im Internet? -> Leitungsprobleme
Prüft dein Antiviren-Programm jede Dateiveränderung? -> Vielleicht mal für einen Test ausschalten.
Wie oben schon geschrieben: Dauert die Bereitstellung der Quelldaten vielleicht lange?

Hast du schon den Debugger benutzt? Eine halbe Sekunde pro Datensatz würdest du beim Debuggen sicher bemerken, wenn es nur durch eine Befehlszeile passiert.

IBExpert 25. Feb 2021 08:15

AW: Anfängerfrage zu SQL-Insert
 
Zitat:

Zitat von Union (Beitrag 1483725)
Bei vielen nicht korrekt abgeschlossenen Transkationen (z.b. killen des Prozesses beim Debgging) macht Firebird generell schwerste Probleme. Ich hatte gerade letzte Woche den Fall, dass ein Datenimport (640.000 Inserts mit 19 Feldern) anstelle von bisher 5 Minuten 6 Stunden benötigte.

Nach Backup + Restore war alles wieder schnell wie bisher.

Nicht FIrebird macht da schwerste Probleme, sondern wie fast immer derjenige, der an der Tastatur sitzt oder das Werkzeug, was der da benutzt.

Und ja, Transaktionen lange offen halten ist immer eine blöde idee, 5 minuten auf 6 Stunden bringen erfordert aber weit mehr als irgendwann
mal im debugging abgebrochen zu haben, wenn das problem an firebird liegen sollte. Und ich bin mir ziemlich sicher, das ein Blick in die MON$
Tabellen gezeigt hätten, welche Transaktionen da ggf. das Problem ausgelöst haben und ein ganz simpler delete from mon$attachment oder den
dienst neu starten hätte auch gereicht.

Was ado oder die Komponente da veranstaltet oder warum bei euch der firebird so lahm ist, kann man per ferndiagnose natürlich schlecht sagen, aber ein weg das
zu beschleunigen ist eben wenn das mal auftritt beim Entwickler, einfach mal den Dienst neu starten, am besten aber vorher noch in mon$attachments
und mon$transactions reinschauen oder in ibexpert auf services-database monitoring in die gleichen bereichen (dort könnt ihr hängende
Transaktionen auch gleich beenden).

Und als weiterer Tip noch mal: prüft mal mit dem Benchmark wie schnell eure Maschine mit Firebird ist

und noch was, stell um auf parametrisierte queries (keine ahnung ob ado commandtext das kann, wenn nicht, dann mach das besser gleich richtig und nehm native komponenten, mit denen das geht

//sql wird außerhalb der schleife nur ein mal gesetzt
adoCommand1.commandText := 'insert into bla values (:p1, :p2, :p3);';
//falls es das gibt, mach ein prepare
adoCommand1.prepare;
Sw.Start;
for i := 0 to 2000 do
begin
//innerhalb der schleife dann nur noch parameter zuweisen
adoCommand1.parambyname('p1').AsInteger:=i+1;
adoCommand1.parambyname('p2').AsInteger:=i+2;
adoCommand1.parambyname('p3').AsInteger:=i+3;
adoCommand1.execute;
end;
Sw.Stop;


und wie schon gesagt, versuch nicht mit irgendwelchen ungeeigneten Komponenten überhaupt erst deinen Quelltext aufzubauen, die umstellung nachher auf performante Versionen lässt sich vermeiden, in dem man gar nicht erst mit ungeeignetem Kram anfängt.

Und wie schon gesagt, wenn du beispiele hier postest, ergänzen dein ddl und mach nicht irgendwelche umgestellten bla bla beispiele, oft sind kleine details der Grund, tabelle ohne indizes, ohne primary keys, dafür aber mit endlos triggerversuchen zB verlieren die zeit ganz woanders und nicht in dem Pseudo code.

ich stell die auswahl über ado zu gehen grundsätzlich bei allen delphi versionen in frage, aber vielleicht siehst du dafür ja gründe (man könnte ja mal umstellen wollen auf andere plattformen ist keiner, dann nimm lieber firedac oder ibdac ...)


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:08 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz