![]() |
Datenbank: Fierbird embedded • Version: 2.1 • Zugriff über: Interbase
Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Hallo,
ich habe mich an einem kleinen Datenbank-Programm versucht und bekomme beim Füllen der Datenbank mit Daten den Fehler "Zu wenig Arbeitsspeicher", nachdem ca. 180 000 Datensätze geschrieben wurden. Eckdaten: Delphi 7 prof. (alle verfügbaren und relevanten Updates von Embarcadero installiert) Bei der Datenbank handelt es sich um eine Firebird-Datenbank (embedded). Ich nutze die Interbase-Komponenten von Delphi 7. Hier der Teil, der den Speicherfehler verursacht: Ich lese aus der Textdatei C:\daten.txt die Daten zeilenweise aus und übertrage sie folgendermaßen in die Datenbank.
Delphi-Quellcode:
Lasse ich das Schreiben in die Datenbank weg, tritt der Fehler nicht auf.
AssignFile(F, 'C:\daten.txt');
reset(F); repeat begin readln(F, temp); x := x + 1; form1.DataSet1.append; form1.DataSet1.Edit; form1.DataSet1.FieldByName('NAME').AsString := temp; end until eof(F); showmessage('...fertig. ' + inttostr(x) + ' Datensätze'); Da es ein 32-Bit-Programm ist, beträgt der maximale (virtuelle) Speicher (da noch nicht erweitert, weil keine Ahnung wie...) 2 GB, der durch das Programm belegt werden kann. Zur Laufzeit werden jedoch "nur" ~500 MB RAM-Speicher belegt. Der Rechner hat satt RAM (32 GB) und es ist auch stets genug freier Speicher vorhanden. Ich habe testweise alle 1000 Datensätze
Delphi-Quellcode:
abgesetzt, hat aber den Fehler nicht abgestellt.
DataSet1.ApplyUpdates;
Ferner habe ich
Delphi-Quellcode:
ausprobiert, was nach meinem Kenntnisstand bewirken soll, das die Änderungen sofort in die Datenbank geschrieben werden sollen und nicht im
DataSet1.CachedUpdates :=false;
virtuellen Speicher zwischengespeichert werden sollen. Das hat auch nichts gebracht. Weiss jemand, woran es liegt und was zu tun ist? |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Das Edit ist nicht notwendig, da Append direkt in den Editmodus wechselt. Ich würde einen expliziten Post einfügen.
Wie sehen die Transaktionseinstellungen aus? |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Mit dem Post in der Schleife hat es auch nichts geändert.
Ich habe eine Transaction1 in dem Programm, welche beim Programmstart aktiv geschaltet wird. Die anderen Eigenschaften der Transaction1 habe ich bis auf die Datenbank nicht verändert. Welche Eigenschaften interessieren dich? |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Zitat:
Versuch doch mal, die Transaktion vor dem Einfügen zu beenden. Geht es dann? |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Zitat:
|
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Ich habe die Tranaction vor dem Einfügen deaktiviert.
Der Fehler bleibt davon aber unberührt. Wenn die Transaktion nicht active ist, macht es da denn dann in Bezug auf den Fehler überhaupt Sinn, diese zu committen und dann wieder neu zu starten? Ich hatte auch getestet, alle 1000 Datensätze das Dataset zu deactivieren und dann wieder vor dem nächsten Datensatz zu activieren, aber das brachte auch keinen Erfolg. Kann denn der virtuelle Speicher, der durch das Dataset belegt ist, wieder freigegeben werden ähnlich dem free einer stringlist? |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
In FireBird geht nichts ohne Transaktionen. Selbt reine Lesezugriffe benötigen einen Transaktionskontext.
Führ mal regelmässig einen Commit durch. (Z.B. je 1000 Datensätze). |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Hallo,
ich würde auf Query umstellen. Wer weiss, wass diese TTable-Dingens im Hintergrund alles anstellt, um auf einen SQL-Server zugreifen zu können, u.a. werden die Daten ja lokal (in der Exe) gecacht. |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
"auf Query umstellen, wer weiß .." würde ich nicht unbedingt, auch wenn es nicht sicher nicht verkehrt wäre. Aber finde ich trotzdem ein gutes Stichwort:
Falls das Dataset noch an die UI gebunden ist, dann rappelt es natürlich ganz schön. |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Zitat:
|
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Da eigentlich alles wichtige schon geschrieben wurde, noch eine Kleinigket, es fehlt das "Closefile".
Gruß K-H |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Hallo,
vielleicht hilft ja auch ein form1.DataSet1.DisableControls aber wie schon vorher gesagt -> TQuery benutzen |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Zitat:
Und wer will sie nachher sehen? (EnableControls nach Import) Eine UI Bindung gehört da gar nicht hin. Ist aber ja auch nur Spekulation, dass eine da ist. |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Was hat dein Dataset denn für einen Typ?
Wie sieht die Datenbankanbindung aus? |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Hallo,
ich habe die Hinweise von euch entsprechend ausprobiert/getestet. 1. alle 1000 Datensätze ein Transaction1.Commit -> Fehler tritt weiterhin auf 2. -> form1.DataSet1.DisableControls -> Fehler tritt auch auf Nur zur Info: An dem Dataset hängt nichts mehr dran. Ich habe das MiniProgramm lediglich zum Befüllen der Datenbank mit Daten aus der besagten Textdatei. @TigerLilly Ist ein TIBDataSet, ein TIBDatabase und ein TIBTransaction, wenn Du das meintest mit der Frage. |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Ich vermute, dass dein TIBDataSet immer alle Datensätze enthält, die du appended hast, auch wenn du es zwischendurch schließt + wieder öffnest (was steht denn im SelectSQL?).
Setze das SelectSQL mal auf select .... Where 1<>1. Damit lädt das SelectSQL nach dem schließen/öffnen keine Sätze aus der DB + enthält nur die Sätze, die du angefügt hast. Alternative: Anstelle des TIBDataSets kannst du dir ja die insert-statements selber bauen und sie via IBSQL direkt in die Datenbank schreiben. Das geht auch flotter. |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Hallo,
die Alternative mit der Query wurde bereits gesagt (von mir :)) |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Zitat:
Nein, im Ernst, sorry, ich wollte nur extra nochmal darauf hinweisen + nicht mit deinen Lorbeeren hausieren. |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Wenn es wirklich daran liegt, daß die Embedded DB zuviel Speicher braucht, könnte man mal versuchen, die Connection zwischendurch zu schließen und wieder neu zu öffnen.
|
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Zitat:
Bei MS Access gabs über ADO die Option Serverseitige Curser zu verwenden damit bei einer TTable-Komponenten nicht der komplette Tabelleninhalt von der Access-Engine nochmal in die Delphi-Teil der Anwendung kopiert wurde. Evtl. gibt das auch bei Interbase. Ansonsten ist ein TTable-Komponenten nicht zu empfehlen bei Inserts und man sollte Query-KOMponenten mit angepassten INSERT-Statements verwenden. Damit ist man 100%ig sicher das nicht versehentlich die ganze Tabelle in den Speicher geladen wird. |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Zitat:
|
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Ja, aber könnte es dann nicht so sein, dass sowohl die DLL, als auch die DataSet-Komponente die gesamten Daten separat im Speicher vorhalten?
Damit hätte doch dann die Anwendung die Daten zweimal im Speicher? Oder ein anderer Ansatz: Statt mit 'nem DataSet und Append, 'ne Query nehmen. Das könnte dann sinngemäß ungefähr (ungetestet) so aussehen:
Delphi-Quellcode:
AssignFile(F, 'C:\daten.txt');
reset(F); form1.Query1.SQL.Clear; form1.Query1.SQL.Add('EXECUTE BLOCK BEGIN'); repeat begin readln(F, temp); x := x + 1; form1.Query1.SQL.Add(Format('insert into tabellenname (Name) Values (%s);',[QuotedStr(temp)])); // Jeweils 1000 Namen "am Stück" in die Tabelle einfügen. // Statt 1000 ggfls. einen angepassten größeren oder kleineren Wert nehmen. if x Mod 1000 do begin form1.Query1.SQL.Add('END'); form1.Query1.ExecSQL; form1.Query1.SQL.Clear; form1.Query1.SQL.Add('EXECUTE BLOCK BEGIN'); end; end until eof(F); if form1.Query1.SQL.Count > 1 then begin form1.Query1.SQL.Add('END'); form1.Query1.ExecSQL; form1.Query1.SQL.Clear; end; CloseFile(f); showmessage('...fertig. ' + inttostr(x) + ' Datensätze'); |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Schönes Beispiel, aber ein Fehler ist da drinnen:
Delphi-Quellcode:
Da kann mit einem falschen String in der Textdatei Blödsinn passieren.
form1.Query1.SQL.Add(Format('insert into tabellenname (Name) Values (%s);',[QuotedStr(temp)]));
Besser mit Parametern arbeiten:
Delphi-Quellcode:
x musst Du halt als Zahl hochzählen.
form1.Query1.SQL.Add('insert into tabellenname (Name) Values (:ParamX);');
form1.Query1.Params[x]:=temp; (Auch ungetestet) |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Zitat:
|
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Da ich bisher noch nicht so intensive Bekanntschaft mit embedded Servern hatte, ich meine mich zu erinnern, daß da lokal einige Services laufen, darum bin ich davon ausgegangen, das das Client-Programm zwar auf der selben Maschine aber ansonsten unabhängig von der DB läuft? (z.B. InterbaseServer)
Gruß K-H |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Embedded bedeutet, dass die Client-Dll den Serverkern enthält. Keine externen Services usw.
|
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Ok, Danke!
Gruß K-H |
AW: Fehler "Zu wenig Arbeitsspeicher" beim Füllen der Datenbank
Wie ist den die Firebird Datenbank Konfiguriert
- Pagesize - Buffers DefaultDbCachePages - werden UDF verwendet - Forcedwrites - MaxUnflushedWrites wo liegt ggf da Temp Verzeichniss und wieviel Platz ist da frei Pagesize*Buffers ist die Anzahl Bytes die Firebird im Cache vorhält (bei embeded) Speicherverbrauch bei offenen Transactionen ![]() mfg Hannes |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:12 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