Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Append Code optimieren aber was macht Sinn? (https://www.delphipraxis.net/156413-append-code-optimieren-aber-macht-sinn.html)

Piro 1. Dez 2010 11:15

Datenbank: MS SQL 2005 • Version: Express • Zugriff über: ADO

Append Code optimieren aber was macht Sinn?
 
Moin zusammen,

Ich lesen ca. 1000 Datensätze mit folgendem Code ein, welcher ca. 15 Sekunden dauert. Ich verwende TADOConnection und TADODataSet.

Delphi-Quellcode:
...
 if FileExists(path_canban) = True then
 begin
   AssignFile(F, path_canban);
   Reset(F);

   while not EoF(F) do
   begin
     Readln(F, zeile);
     sl_zeile := Split(zeile,';', True); // ist nicht das Problem
     Inc(counter);

     try
       DSData.Close;
       DSData.CommandText := 'Select * from fullload_data';
       DSData.Open;

       DSData.Append;
       DSData.FieldByName('lname').AsString         := sl_zeile[0];
       DSData.FieldByName('sachnr').AsString        := sl_zeile[1];
       DSData.FieldByName('benennung').AsString     := sl_zeile[2];
       DSData.FieldByName('zeichnungsnr').AsString  := sl_zeile[3];
       DSData.FieldByName('lagerbestand').AsString  := sl_zeile[4];
       DSData.FieldByName('liefermenge').AsString   := sl_zeile[5];
       DSData.FieldByName('mindestbestand').AsString := sl_zeile[6];
       DSData.FieldByName('abrufnr').AsString       := sl_zeile[7];
       DSData.FieldByName('tag').AsString           := sl_zeile[8];
       DSData.FieldByName('abrufnr_zusatz').AsString := sl_zeile[9];
       DSData.FieldByName('aindex').AsString        := sl_zeile[10];
       DSData.FieldByName('lieferort').AsString     := sl_zeile[11];
       DSData.FieldByName('position').AsString      := sl_zeile[12];
       DSData.FieldByName('kenn_es').AsString       := ''; //sl_zeile[13];
       DSData.FieldByName('lnr').AsString           := ''; //sl_zeile[14];
       DSData.Post;

       DSData.Close;
     Except
       //
     end;
   end;
   tbtn_fullload_import.Enabled := False;
 end;
...
In der Zukunft können sich die Daten verdoppeln. So, dass das Program 30 Sekunden braucht. Das ist nicht wirklich schlimm aber kann man es noch optimieren?

Ich habe es schon mit BULK INSERT versucht. Geht verdammt schnell. Leider gibt es ein paar Sachen, die dann nicht mehr funktionieren, die ich wärend des Insert benötige.

Über TADOQuery könnte man es auch machen aber ich weiß nicht, ob der Unterschied so groß ist. Bei TADODataSet habe ich auch schon die Eigenschaft Prepare=True gesetzt. Passiert aber nichts.

Meine Idee wäre, alle Daten mit Append in die Datenbank schreiben und zum Schluss ein Post. Leider habe ich dann nur einen Datensatz in der DB.

Habe das Forum schon einwenig durchsucht, was mich nicht weitergebracht hat.

Vielleicht sieht ja einer meinen Quellcode und weiß sofort, wo man was optimieren kann. Verständnisfehler sind nicht ausgeschlossen.

Vielen Dank im Voraus.
Sven

Bernhard Geyer 1. Dez 2010 11:21

AW: Append Code optimieren aber was macht Sinn?
 
Am besten einen BULK-INSERT selbst zusammenbauen (so 10-50 Inserts)
Code:
INSERT INTO fullload_data(...) VALUES(...)
INSERT INTO fullload_data(...) VALUES(...)
INSERT INTO fullload_data(...) VALUES(...)
INSERT INTO fullload_data(...) VALUES(...)
und dann als ein Statement zur DB senden.


und immer schön mit parametern und prepared Statements arbeiten.

guinnes 1. Dez 2010 11:26

AW: Append Code optimieren aber was macht Sinn?
 
Das andauernde FieldByName macht die Sache sicherlich auch nicht schneller. Hast du es schon mal mit persistenten Feldern versucht ?

himitsu 1. Dez 2010 11:29

AW: Append Code optimieren aber was macht Sinn?
 
Wenn du dieses außerhalb der Schleife nur einmal machst?
Delphi-Quellcode:
DSData.Close;
DSData.CommandText := 'Select * from fullload_data';
DSData.Open;

// und

DSData.Close;
Das mit dem .Post ist klar. Da werden dann jedesmal die gleichnamigen) Werte überschrieben und dann am Ende alles nur einmal abgesendet.

dataspider 1. Dez 2010 11:33

AW: Append Code optimieren aber was macht Sinn?
 
Wenn ich jetzt nicht völlig blind bin, würde ich sagen, dass das ständige Öffnen und Schliessen des DataSet überflüssig ist.

Frank

EDIT:
Code:
if FileExists(path_canban) = True then
begin
  AssignFile(F, path_canban);
  Reset(F);
  DSData.Close;
  DSData.CommandText := 'Select * from fullload_data';
  DSData.Open;
  while not EoF(F) do
  begin
    Readln(F, zeile);
    sl_zeile := Split(zeile,';', True); // ist nicht das Problem
    Inc(counter);
    try
      DSData.Append;
      DSData.FieldByName('lname').AsString := sl_zeile[0];
      DSData.FieldByName('sachnr').AsString := sl_zeile[1];
      ..
      DSData.Post;
    Except
      //
    end;
  end;
  DSData.Close;
  ...

Piro 1. Dez 2010 12:09

AW: Append Code optimieren aber was macht Sinn?
 
An alle, die mir den Tipp geben haben, dass ich das Öffnen der Tabelle vor die Schleifen legen solle, ein herzlichen Dank.

Das hat 50% Zeit eingespart.

jetzt werde ich mir noch die anderen Vorschläge anschauen. Vielleicht geht es ja noch schneller und komme an die Zeit des BULK INSERT.

Vielen Dank nochmal für eure Hilfe.

gruß, Sven

Sir Rufo 1. Dez 2010 12:46

AW: Append Code optimieren aber was macht Sinn?
 
CSV-Dateien kann man auch per ADO öffnen Hier im Forum suchenCSV
(ok, den Hinweis hatte ich dir schon gegeben ... scheint also wohl nicht interessant zu sein)

Der Insert geht wesentlich schneller mit einem "prepared" INSERT-Statement mit Parametern.
Weiterhin sollte man den kompletten INSERT innerhalb einer Transaktion durchführen.
Einige DBMS aktualisieren die Indizes nämlich erst nach Abschluss der Transaktion.

SQL-Code:
INSERT INTO tab ( fld1, fld2, fld3, fld4 )
VALUES ( :fld1, :fld2, :fld3, :fld4 )
PS: Nach meiner Erfahrung ist das Öffnen der gesamten Tabelle um dann mit Append und Post neue Datensätze einzufügen, die langsamste Variante, die man wählen kann
Um das Übertragen der bestehenden Datensätze zu verhindern, solltest du den SELECT wie folgt aufrufen:
SQL-Code:
SELECT * FROM fullload_data WHERE 1 = 0

shmia 1. Dez 2010 12:57

AW: Append Code optimieren aber was macht Sinn?
 
Die Klausel WHERE 0=1 verhindert, dass unnötigerweise Daten vom Server gelesen werden.
Delphi-Quellcode:
DSData.Close;
DSData.CommandText := 'Select * from fullload_data WHERE 0=1';
DSData.Open;

Sir Rufo 1. Dez 2010 12:59

AW: Append Code optimieren aber was macht Sinn?
 
Zitat:

Zitat von shmia (Beitrag 1065399)
Die Klausel WHERE 0=1 verhindert, dass unnötigerweise Daten vom Server gelesen werden.
Delphi-Quellcode:
DSData.Close;
DSData.CommandText := 'Select * from fullload_data WHERE 0=1';
DSData.Open;

Aber anscheinend steht er auf kompliziert, unflexibel und langsam :mrgreen:

Piro 1. Dez 2010 13:26

AW: Append Code optimieren aber was macht Sinn?
 
Das mit den CSV Dateien hatte ich auch schon mal gemacht. War meine erste Lösung. Nun haben sich aber die Anforderungen geändert und die Daten müssen nun in eine MS SQL Datenbank, um komplexe Abfragen zu erstellen.

Wie müsste man das mit dem "prepared" INSERT-Statement mit Parametern machen. Mir fehlt gerade der Ansatz. Müsste ich dann TADOQuery oder TADOCommand benutzen?

Eins hatte ich noch vergessen. Meine Datenbanktabelle wird vor dem Import geleert mit. Also keine alten Daten vorhanden.
Delphi-Quellcode:
// TADOCommand Komponente
SQLCommand.CommandText := 'TRUNCATE TABLE fullload_data';
SQLCommand.Execute;


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:54 Uhr.
Seite 1 von 2  1 2      

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