![]() |
Datenbank: DBISAM • Version: 4 • Zugriff über: DBISAMQuery
Insert-Schleife viel zu langsam
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; |
AW: Insert-Schleife viel zu langsam
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. |
AW: Insert-Schleife viel zu langsam
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. ![]() 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. |
AW: Insert-Schleife viel zu langsam
Es ist auch erheblich schneller, mehrere Sätze in einem Insert zu machen:
Code:
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.
INSERT INTO foo VALUES (bar1, peng1), (bar2, peng2), (bar3, ...
|
AW: Insert-Schleife viel zu langsam
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; |
AW: Insert-Schleife viel zu langsam
Zitat:
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 ![]() ![]() PS: SL ist eine sehr gut benamte externe Variable. :thumb: |
AW: Insert-Schleife viel zu langsam
Zitat:
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. ;) |
AW: Insert-Schleife viel zu langsam
AppendRecord macht
Delphi-Quellcode:
und das geht doch wohl auch mehrmals hintereinande, ohne jedesmal die Tabelle neu auf+zu zumachen?
Append;
// Felder setzen Post; Eventuell auch noch ein DisableControls/EnableControls drumrum. Zitat:
|
AW: Insert-Schleife viel zu langsam
Zitat:
|
AW: Insert-Schleife viel zu langsam
[OT] Ich dachte, das hieße Santa Laus :mrgreen: [/OT]
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:18 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 by Thomas Breitkreuz