AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Insert-Schleife viel zu langsam
Thema durchsuchen
Ansicht
Themen-Optionen

Insert-Schleife viel zu langsam

Ein Thema von Partikelecho · begonnen am 2. Dez 2011 · letzter Beitrag vom 10. Dez 2011
Antwort Antwort
Seite 1 von 2  1 2      
Partikelecho

Registriert seit: 2. Dez 2011
14 Beiträge
 
Delphi 6 Enterprise
 
#1

Insert-Schleife viel zu langsam

  Alt 2. Dez 2011, 08:20
Datenbank: DBISAM • Version: 4 • Zugriff über: DBISAMQuery
Guten Morgen,
Ich bin neu hier, also verzeiht mir eventuell falsch genutzte Foren, o.ä. fürs Erste.

Meine Aufgabe ist das Programmieren einer Anwendung zum Auslesen von Ordnern (welche immer eine Datenbank sind, also Pfad = Datenbank) und das darstellen der Dateiinformationen in einem DBGrid.

Ich verwende Delphi 6 und soweit ich weiß DBISAM 4 (kann ich im moment nicht überprüfen).
Mein Problem ist, dass zwar die FindAllFiles-Funktion und die Variablenzuweisung in der Schleife relativ schnell gehen, das Inserten von 40.000 Datensätzen in etwa 8 bis 10 Minuten dauert.

- Version mit Parametern statt direkter Variablenübergabe ist noch langsamer
- Bulkinsert von jeweils 50, 100 oder 1000 SQL-Inserts dauert in etwa genau so langsam.
- Die Funktionen GetFileTimes & GetFileSize laufen auch nur ein paar Sekunden.
- Kommentiere ich den SQL-Teil ab with aus, so dauert es ebenfalls nur ca. 10 Sekunden (gut, immernoch zu lange, aber im Vergleich zu Minuten..)
- SL[i] (eine Stringlist) enthält die einzufügenden Dateien.

Delphi-Quellcode:
procedure TFRM_Main.ReadInInvA;
var
  i, invasize:Integer;
  inva, invaaccessed, invacreated, invamodified:String;
  created, accessed, modified:TDateTime;
begin
  QRY_Container.SQL.Clear;
  inva := invaname;
  for i := 0 to SL.Count-1 do
  begin
    if GetFileTimes(CXBE_DbDir.Text+’\‘SL[i], created, accessed, modified) then
    begin
      invaaccessed := DateTimeToStr(accessed);
      invacreated := DateTimeToStr(created);
      invamodified := DateTimeToStr(modified);
    end;
    invasize := GetFileSize(CXBE_DbDir.Text’\‘+SL[i]);
    with QRY_Container do
    begin
      SQL.Add(’INSERT INTO ‘inva’(INVA_FILE, INVA_FILE_CREATED,‘+
              ’INVA_FILE_ALTERED, INVA_FILE_VIEWED, INVA_FILE_SIZE) VALUES’+
              ’ (’’’+SL[i]‘’’,‘’’invacreated+’’’,‘+
              ’’’’+invamodified+’’’,’’’+invaaccessed+’’’,‘inttostr(invasize)’);’);
      if i > 0 then
      begin
        if (i mod 1000) = 0 then
        begin
          ExecSQL;
          SQL.Clear;
        end;
      end;
      if i = SL.Count-1 then
      ExecSQL;
      // 1000 Insert-Befehle werden hintereinander geschrieben und dann zusammen ausgeführt.
    end;
  end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.202 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Insert-Schleife viel zu langsam

  Alt 2. Dez 2011, 08:44
Prepared Statements mit Parameter sollten schneller sein.
DBISAM ist eine Destkop-Datenbank. Hier solltest du deinen Virenscanner so einstellen das die enstprechenden DB-Dateien nicht untersucht weden.

Wie viele Indizes gibt es auf deiner Tabelle. Je mehr desto langsamer ist auch ein Insert. Hier bremst im gegensatz zu Abfragen jeder Index.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
tankard

Registriert seit: 5. Mai 2006
2 Beiträge
 
#3

AW: Insert-Schleife viel zu langsam

  Alt 2. Dez 2011, 09:28
hi,

also so kann das nur langsam sein.
da bei jedem insert die daten direkt auf platte geschrieben werden.
schau mal ob das datenbanksystem auch transactions kann. mal nach googlen was das ist. http://www.firstsql.com/tutor5.htm

gruss
tankard

ps: nur weil du 1000 sql statements zusammenfuegst, werden diese doch der reihe nach abgearbeitet, insert befehle ohne transaction, werden direkt auf platte geschrieben. daher hast du bei 1000 inserts, 1000 plattenzugriffe. wenn du tranaktionen nutzt, wird nach einem commit nur einmal alles weggeschrieben.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#4

AW: Insert-Schleife viel zu langsam

  Alt 2. Dez 2011, 10:03
Es ist auch erheblich schneller, mehrere Sätze in einem Insert zu machen:
Code:
INSERT INTO foo VALUES (bar1, peng1), (bar2, peng2), (bar3, ...
Wie viele Sätze man in so ein Statement hängen kann, hängt vom DBMS ab (bzw. ist spätestens nach 2GB wegen Stringlänge Ende ), aber ich hab mit 100 am Stück zumindest noch nie Probleme bekommen, und die reichten mir bislang für einen deftigen boost.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Partikelecho

Registriert seit: 2. Dez 2011
14 Beiträge
 
Delphi 6 Enterprise
 
#5

AW: Insert-Schleife viel zu langsam

  Alt 7. Dez 2011, 07:49
Hallo,
Ich hab nun endlich wieder Zugriff auf meine Source gehabt und wollte euch noch zeigen, wie ich die Zeit massiv verkürzen konnte, in der die Dateien eingelesen werden.

tankards Vorschlag mit Transactions zu arbeiten war zielführend.
Zusätzlich habe ich den Insertpart durch AppendRecord ersetzt.
Falls ihr noch Verbesserungsvorschläge habt, wie ich die Zeit weiter verkürzen könnte, dann immer her damit.

Danke für eure Hilfe..

Delphi-Quellcode:
procedure TFRM_Main.ReadInInvA;
var
  i, invasize:Integer;
  invaaccessed, invacreated, invamodified:String;
  created, accessed, modified:TDateTime;
begin
  DB_Container.Directory := CXBE_InvDir.Text;
  DB_Container.Open;
  TBL_Container.DatabaseName := DB_Container.DatabaseName;
  DB_Container.StartTransaction;
  for i := 0 to SL.Count-1 do
  begin
    if GetFileTimes(CXBE_DbDir.Text+’\‘+SL[i], created, accessed, modified) then
    begin
      invaaccessed := DateTimeToStr(accessed);
      invacreated := DateTimeToStr(created);
      invamodified := DateTimeToStr(modified);
    end;
    invasize := GetFileSize(CXBE_DbDir.Text+’\’+SL[i]);
    with TBL_Container do
    begin
      DatabaseName := DB_Container.DatabaseName;
      TableName := invaname;
      Open;
      AppendRecord([null, SL[i], invacreated, invamodified, invaaccessed, invasize]);
      Close;
    end;
  end;
  DB_Container.Commit;
  DB_Container.Close;
end;

Geändert von Partikelecho ( 7. Dez 2011 um 08:03 Uhr) Grund: Code-Tag gefixt
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

AW: Insert-Schleife viel zu langsam

  Alt 7. Dez 2011, 08:03
Zitat:
Delphi-Quellcode:
      DatabaseName := DB_Container.DatabaseName;
      TableName := invaname;
      Open;
      ...
      Close;
Diese Teile ändern sich nicht.
Wieso also nicht einfach nur einmal for/nach der For-Schleife?

Statt der vielen FileTime- und FileSize-Funktionen könnte man es mal mit einem MSDN-Library durchsuchenFindFirstFile versuchen. (das ganze Geraffel vom Delphi-Referenz durchsuchenFindFirst kann man sich hier sparen)


PS: SL ist eine sehr gut benamte externe Variable.
$2B or not $2B
  Mit Zitat antworten Zitat
Partikelecho

Registriert seit: 2. Dez 2011
14 Beiträge
 
Delphi 6 Enterprise
 
#7

AW: Insert-Schleife viel zu langsam

  Alt 7. Dez 2011, 08:11
Zitat:
Delphi-Quellcode:
      DatabaseName := DB_Container.DatabaseName;
      TableName := invaname;
      Open;
      ...
      Close;
Diese Teile ändern sich nicht.
Wieso also nicht einfach nur einmal for/nach der For-Schleife?
Aber hat dieser Teil dann nicht nur die Werte des letzten Schleifendurchlaufs? Es werden doch immer jeweils die Variablen neu erstellt und für jede Datei neu hinzugefügt.

Statt der vielen FileTime- und FileSize-Funktionen könnte man es mal mit einem MSDN-Library durchsuchenFindFirstFile versuchen. (das ganze Geraffel vom Delphi-Referenz durchsuchenFindFirst kann man sich hier sparen)


PS: SL ist eine sehr gut benamte externe Variable.
Damit werde ich mich noch auseinandersetzen, ich hatte ohnehin vor, diese Funktionen noch anzupassen/ zu verbessern.

Naja gut, SL wird in dem Programm immer mal wieder verwendet, es hat einen allgemeinen Zweck und wird nicht stetig gebraucht. Deswegen ist der Bezeichner SL so geblieben.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#8

AW: Insert-Schleife viel zu langsam

  Alt 7. Dez 2011, 08:23
AppendRecord macht
Delphi-Quellcode:
Append;
// Felder setzen
Post;
und das geht doch wohl auch mehrmals hintereinande, ohne jedesmal die Tabelle neu auf+zu zumachen?

Eventuell auch noch ein DisableControls/EnableControls drumrum.


Zitat:
Naja gut, SL wird in dem Programm immer mal wieder verwendet, es hat einen allgemeinen Zweck und wird nicht stetig gebraucht. Deswegen ist der Bezeichner SL so geblieben.
Also eine unbestimmte globale Variable, bei der man nie genau weiß, was sich nun gerade dort drin befindet?
$2B or not $2B

Geändert von himitsu ( 7. Dez 2011 um 08:26 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Insert-Schleife viel zu langsam

  Alt 7. Dez 2011, 09:29
Zitat:
Naja gut, SL wird in dem Programm immer mal wieder verwendet, es hat einen allgemeinen Zweck und wird nicht stetig gebraucht. Deswegen ist der Bezeichner SL so geblieben.
Also eine unbestimmte globale Variable, bei der man nie genau weiß, was sich nun gerade dort drin befindet?
Hierbei handelt es sich um das StringLuder. Da darf jeder mal ran und was reinstecken und man weiß eigentlich nie, was man so richtig bekommt, aber meistens geht hoffentlich alles gut.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.625 Beiträge
 
Delphi 12 Athens
 
#10

AW: Insert-Schleife viel zu langsam

  Alt 7. Dez 2011, 09:30
[OT] Ich dachte, das hieße Santa Laus [/OT]
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:15 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