![]() |
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:
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?
...
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; ... 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 |
AW: Append Code optimieren aber was macht Sinn?
Am besten einen BULK-INSERT selbst zusammenbauen (so 10-50 Inserts)
Code:
und dann als ein Statement zur DB senden.
INSERT INTO fullload_data(...) VALUES(...)
INSERT INTO fullload_data(...) VALUES(...) INSERT INTO fullload_data(...) VALUES(...) INSERT INTO fullload_data(...) VALUES(...) und immer schön mit parametern und prepared Statements arbeiten. |
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 ?
|
AW: Append Code optimieren aber was macht Sinn?
Wenn du dieses außerhalb der Schleife nur einmal machst?
Delphi-Quellcode:
Das mit dem .Post ist klar. Da werden dann jedesmal die gleichnamigen) Werte überschrieben und dann am Ende alles nur einmal abgesendet.
DSData.Close;
DSData.CommandText := 'Select * from fullload_data'; DSData.Open; // und DSData.Close; |
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; ... |
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 |
AW: Append Code optimieren aber was macht Sinn?
CSV-Dateien kann man auch per ADO öffnen
![]() (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:
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
INSERT INTO tab ( fld1, fld2, fld3, fld4 )
VALUES ( :fld1, :fld2, :fld3, :fld4 ) 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
|
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; |
AW: Append Code optimieren aber was macht Sinn?
Zitat:
|
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 11:44 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-2025 by Thomas Breitkreuz