Delphi-PRAXiS
Seite 1 von 5  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Schnellste Insert Möglichkeit für eine DB? (https://www.delphipraxis.net/148461-schnellste-insert-moeglichkeit-fuer-eine-db.html)

moelski 2. Mär 2010 12:00

Datenbank: FireBird • Version: 2.5 • Zugriff über: UniDac

Schnellste Insert Möglichkeit für eine DB?
 
Moin !

Was ist eigentlich die schnellste Variante, Daten in einer DB einzutragen?

Nehmen wir mal an ich möchte die Daten eines Messgeräts in eine Tabelle sichern. Dann gibt es da (soweit ich das bis hier überblicke) 2 Methoden:
1) mittels FieldByName / Append
Delphi-Quellcode:
DBQuery.Edit;
DBQuery.FieldByName('ID').AsInteger            := Counter;
DBQuery.FieldByName('PROP01').AsFloat          := Random(10000) / 10;
DBQuery.FieldByName('PROP02').AsFloat          := Random(10000) / 10;
DBQuery.FieldByName('PROP03').AsFloat          := Random(10000) / 10;
DBQuery.FieldByName('DateTime').AsSQLTimeStamp := DateTimeToSQLTimeStamp(Now);
DBQuery.Append;
2) mittels SQL Insert (und das dann eben mit x Werten in einem SQL Statement)
Delphi-Quellcode:
DM.Query.SQL.Text := 'INSERT Into Demo (demo.wert1) VALUES (100);';
DM.Query.ExecSQL;
Aber was geht nun am schnellsten? Und gibt es noch andere Varianten?

Sharky 2. Mär 2010 12:08

Re: Schnellste Insert Möglichkeit für eine DB?
 
Zitat:

Zitat von moelski
... Aber was geht nun am schnellsten? Und gibt es noch andere Varianten?

Ich denke das Variante 2 unter verwendung von Parametern am schnellsten sein sollte.

chaosben 2. Mär 2010 12:43

Re: Schnellste Insert Möglichkeit für eine DB?
 
Nur mal so'n Gedankenfurz: Das schnellste laut HK ist eine Externe Tabelle die man mit
SQL-Code:
insert into tabelle (bla) select bla from externe_tabelle
anzapft.

Die Frage die jetzt noch zu klären wäre: Kann man eine external Table von "außen" beschreiben, während man sie von der DB genutzt wird?

sirius 2. Mär 2010 12:45

Re: Schnellste Insert Möglichkeit für eine DB?
 
SQL-Code:
DM.Query.SQL.Text := 'INSERT Into Demo (demo.wert1) VALUES (100), Values(200), Values(400);';
DM.Query.ExecSQL;

Sharky 2. Mär 2010 13:06

Re: Schnellste Insert Möglichkeit für eine DB?
 
Hi Sirius,

wäre das nicht schneller (bei vielen aufeinander folgenden Eintragungen)?

SQL-Code:
DM.Query.SQL.Text := 'INSERT Into Demo (demo.wert1, demo.wert2, demo.wert3) VALUES (:wert, :wert2, :wert3);';
DM.Query.Prepare;
DM.Query.Params[0].AsInteger := 100;
DM.Query.Params[1].AsInteger := 200;
DM.Query.Params[2].AsInteger := 400;
DM.Query.ExecSQL;
Jetzt muss das DBMS nicht jedesmal den SQL-Query parsen. Für die weiteren Einträge dann natürlich nuch noch Zeile 3-6 ausführen.

moelski 2. Mär 2010 13:28

Re: Schnellste Insert Möglichkeit für eine DB?
 
Moin !

Ich habe mal alle 3 Varianten umgesetzt. (Code siehe unten).

Count : 1000
1 Time : 10390 ms
2 Time : 8016 ms
3 Time : 14952 ms

Count : 100
1 Time : 1062 ms
2 Time : 985 ms
3 Time : 2296 ms

Die Ergebnisse zeigen das es derzeit so ausschaut als wenn die reine Insert Methode die schnellste wäre.
Danach kommt die FieldByName Variante. Und am Ende steht die Parameter Variante von Sharky (was mich sehr erstaunt).

Count bezieht sich auf die anzahl der Datensätze die eingetragen werden.

Hier noch der verwendete Code:
Delphi-Quellcode:
procedure TDBThread.Execute;
var I        : Integer;
    StartTime : TDateTime;
    SQl : String;
begin
  StartTime := Now;
  DBQuery.Edit;
  for I := 1 to Amount do begin
    Inc(Counter);
    DBQuery.FieldByName('ID').AsInteger            := Counter;
    DBQuery.FieldByName('PROP01').AsFloat          := Random(10000);
    DBQuery.FieldByName('PROP02').AsFloat          := Random(10000);
    DBQuery.FieldByName('PROP03').AsFloat          := Random(10000);
    DBQuery.FieldByName('PROP04').AsFloat          := Random(10000);
    DBQuery.FieldByName('PROP05').AsFloat          := Random(10000);
    DBQuery.FieldByName('PROP06').AsFloat          := Random(10000);
    DBQuery.FieldByName('PROP07').AsFloat          := Random(10000);
    DBQuery.FieldByName('PROP08').AsFloat          := Random(10000);
    DBQuery.FieldByName('PROP09').AsFloat          := Random(10000);
    DBQuery.FieldByName('PROP10').AsFloat          := Random(10000);
    DBQuery.FieldByName('DateTime').AsSQLTimeStamp := DateTimeToSQLTimeStamp(Now);

    DBQuery.Append;
  end;
  TimeMS := MilliSecondsBetween(Now, StartTime);
  Form2.Memo1.Lines.Add('1 Time : ' + IntToStr(TimeMS) + ' ms');

  StartTime := Now;
  for I := 1 to Amount do begin
    Inc(Counter);
    SQl :=                   'INSERT Into ' + Table;
    SQl := SQl + ' (ID, PROP01, PROP02, PROP03, PROP04, PROP05, PROP06, PROP07, PROP08, PROP09, PROP10)';
    SQl := SQl + ' VALUES (' + IntToStr(Counter) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ', ';
    SQl := SQl + FloatToStr(Random(10000) ) + ');';
    //SQl := SQl + SQLTimeStampToStr('ddd d of mmm yyyy', DateTimeToSQLTimeStamp(Now)) + ');';
    DBQuery.SQL.Text := SQL;
    DBQuery.ExecSQL;
  end;
  TimeMS := MilliSecondsBetween(Now, StartTime);
  Form2.Memo1.Lines.Add('2 Time : ' + IntToStr(TimeMS) + ' ms');

  StartTime := Now;
  for I := 1 to Amount do begin
    Inc(Counter);
    DBQuery.SQL.Text := 'INSERT Into ' + Table + ' (ID, PROP01, PROP02, PROP03, PROP04, PROP05, PROP06, PROP07, PROP08, PROP09, PROP10) VALUES (:wert1, :wert2, :wert3, :wert4, :wert5, :wert6, :wert7, :wert8, :wert9, :wert10, :wert11);';
    DBQuery.Prepare;
    DBQuery.Params[0].AsInteger := Counter;
    DBQuery.Params[1].AsFloat := Random(10000);
    DBQuery.Params[2].AsFloat := Random(10000);
    DBQuery.Params[3].AsFloat := Random(10000);
    DBQuery.Params[4].AsFloat := Random(10000);
    DBQuery.Params[5].AsFloat := Random(10000);
    DBQuery.Params[6].AsFloat := Random(10000);
    DBQuery.Params[7].AsFloat := Random(10000);
    DBQuery.Params[8].AsFloat := Random(10000);
    DBQuery.Params[9].AsFloat := Random(10000);
    DBQuery.Params[10].AsFloat := Random(10000);
    DBQuery.ExecSQL;
  end;

  TimeMS := MilliSecondsBetween(Now, StartTime);
  Form2.Memo1.Lines.Add('3 Time : ' + IntToStr(TimeMS) + ' ms')
end;

Sharky 2. Mär 2010 13:31

Re: Schnellste Insert Möglichkeit für eine DB?
 
Hai moelski,

ich habe den letzten Absatz in meinem Posting erweitert. Ansonsten machen die Params keinen Sinn.

Test es doch mal so:
Delphi-Quellcode:
    DBQuery.SQL.Text := 'INSERT Into ' + Table + ' (ID, PROP01, PROP02, PROP03, PROP04, PROP05, PROP06, PROP07, PROP08, PROP09, PROP10) VALUES (:wert1, :wert2, :wert3, :wert4, :wert5, :wert6, :wert7, :wert8, :wert9, :wert10, :wert11);';
    DBQuery.Prepare;
   for I := 1 to Amount do begin
    Inc(Counter);
    DBQuery.Params[0].AsInteger := Counter;
    DBQuery.Params[1].AsFloat := Random(10000);
    DBQuery.Params[2].AsFloat := Random(10000);
    DBQuery.Params[3].AsFloat := Random(10000);
    DBQuery.Params[4].AsFloat := Random(10000);
    DBQuery.Params[5].AsFloat := Random(10000);
    DBQuery.Params[6].AsFloat := Random(10000);
    DBQuery.Params[7].AsFloat := Random(10000);
    DBQuery.Params[8].AsFloat := Random(10000);
    DBQuery.Params[9].AsFloat := Random(10000);
    DBQuery.Params[10].AsFloat := Random(10000);
    DBQuery.ExecSQL;
  end;

sirius 2. Mär 2010 13:31

Re: Schnellste Insert Möglichkeit für eine DB?
 
@Sharky
Ja natürlich mit Parametern.
Ich meinte mit meinem Post, dass man auch mehrere Zeilen in einem Insert-Statement unterbringen kann (zumindest in Oracle).

moelski 2. Mär 2010 13:35

Re: Schnellste Insert Möglichkeit für eine DB?
 
@Sharky:
Ich sehe jetzt gerade die Differenz zu meinem Code nicht :gruebel:

Sharky 2. Mär 2010 13:41

Re: Schnellste Insert Möglichkeit für eine DB?
 
Zitat:

Zitat von moelski
@Sharky:
Ich sehe jetzt gerade die Differenz zu meinem Code nicht :gruebel:

Du setzt das SQL-Kommando innerhalb der Schleife. Darum muss es jedes mal neu geparst werden.
Ich setzte es nur einmal und übergebe in der Schleife dann nur die geänderten Parameter.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:12 Uhr.
Seite 1 von 5  1 23     Letzte »    

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