Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi FireDAC Query Speicher freigeben (https://www.delphipraxis.net/197016-firedac-query-speicher-freigeben.html)

haentschman 10. Jul 2018 16:14

Datenbank: MSSQL • Version: 2012 • Zugriff über: FireDAC

FireDAC Query Speicher freigeben
 
Hallöle...:P

Gegeben:
FDQuery auf einem Datamodul mit ca. 300 im Feldeditor eingetragenen Feldern. :?

Auch wenn ich die Query (Resultset mit ca. 500MB) schließe, habe ich nach dem Open (neues SQL mit Parametern) eines Resultsets mit keinem Datensatz keine Verringerung des Arbeitsspeichers... :shock:

Wie kann ich die Query wirklich leeren? (Speicher) :roll:

Uwe Raabe 10. Jul 2018 16:17

AW: FireDAC Query Speicher freigeben
 
Zitat:

Zitat von haentschman (Beitrag 1406874)
Auch wenn ich die Query (Resultset mit ca. 500MB) schließe, habe ich nach dem Open (neues SQL mit Parametern) eines Resultsets mit keinem Datensatz keine Verringerung des Arbeitsspeichers... :shock:

Wie kann ich die Query wirklich leeren?

Die Query ist dann schon leer. Das bedeutet aber nicht, daß der Arbeitsspeicher wieder freigegeben wird (zumindest nicht so, daß Windows das merkt).

Wird denn der Arbeitsspeicher größer, wenn du die Query danach wieder füllst?

Bernhard Geyer 10. Jul 2018 16:25

AW: FireDAC Query Speicher freigeben
 
Zitat:

Zitat von haentschman (Beitrag 1406874)
... keine Verringerung des Arbeitsspeichers...

Nach Windows Taskmanager oder wenn du den Delphi-Speichermanager fragst?

haentschman 10. Jul 2018 16:33

AW: FireDAC Query Speicher freigeben
 
Hallo Uwe...

Langsam verstehe ich die Welt nicht mehr. Ich habe das Statement so manipuliert, daß beim Start max. 10 Datensätze abgerufen werden... was macht der Speicher?...läuft auf 1.2GB :? Gefühlt macht er aus der Query eine Tabelle wo die where Bedingung ignoriert wird. Kann das mit fmAll zusammenhängen?

Zu deiner Frage: Bleibt stabil.

Zitat:

Nach Windows Taskmanager
...ja

Uwe Raabe 10. Jul 2018 16:40

AW: FireDAC Query Speicher freigeben
 
Zitat:

Zitat von haentschman (Beitrag 1406878)
Ich habe das Statement so manipuliert, daß beim Start max. 10 Datensätze abgerufen werden... was macht der Speicher?...läuft auf 1.2GB :? Gefühlt macht er aus der Query eine Tabelle wo die where Bedingung ignoriert wird. Kann das mit fmAll zusammenhängen?

Was passiert denn, wenn du die Query in der IDE im Query-Editor von FireDAC abschickst?

haentschman 10. Jul 2018 16:56

AW: FireDAC Query Speicher freigeben
 
...ich habe keine Verbindung im Editor...habe ich noch nie gemocht. :?

Code:
SELECT DatumBeleg, *
  FROM [Bla].[dbo].[Blubb]
  where AddDate BETWEEN DATEADD([day], -10, GETDATE()) AND (GETDATE())
...1 Datensatz (1,1GB Speicher)

Code:
SELECT DatumBeleg, *
  FROM [Bla].[dbo].[Blubb]
  where AddDate BETWEEN DATEADD([day], -30, GETDATE()) AND (GETDATE())
...3450 Datensätze (1,2GB Speicher)

:gruebel:

Uwe Raabe 10. Jul 2018 17:03

AW: FireDAC Query Speicher freigeben
 
Kannst du das einfach mal ein ein separates Programm packen und nur die Query ausführen? Nur um irgendwelche Seiteneffekte auszuschließen. Probeweise vielleicht auch mal im SQL Management Studio ausführen. Die Query allein ist nicht wirklich aussagekräftig.

haentschman 10. Jul 2018 18:07

AW: FireDAC Query Speicher freigeben
 
:P Heute nicht mehr, ich habe entnervt aufgeben. Morgen wieder... Ich habe noch ein paar Tests im Kopf.

Der schöne Günther 10. Jul 2018 18:45

AW: FireDAC Query Speicher freigeben
 
Das hatte ich auch mal - FireDAC lädt gerne die gesamte Datenbank nur um sie dann auf Client-Seite zu filtern oder zu sortieren. Das treibt er selbst so weit bis ihm als 32-Bit-Prozess der Speicher ausgeht. Da gibt es so unendlich viele Einstellungen in FireDAC, eine davon wird es sein. Ich kann morgen noch einmal nachschauen was ich bei mir ändern musste damit er aufhört.

Uwe Raabe 10. Jul 2018 19:04

AW: FireDAC Query Speicher freigeben
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1406890)
FireDAC lädt gerne die gesamte Datenbank nur um sie dann auf Client-Seite zu filtern oder zu sortieren.

FireDAC kann auch nur maximal soviel Daten laden wie der SQL-Server hergibt. Wenn eine Query nur einen Record liefert, dann müssen das schon ziemlich viele und große Felder sein um 1 GB voll zu bekommen.

Bernhard Geyer 10. Jul 2018 19:35

AW: FireDAC Query Speicher freigeben
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1406891)
Zitat:

Zitat von Der schöne Günther (Beitrag 1406890)
FireDAC lädt gerne die gesamte Datenbank nur um sie dann auf Client-Seite zu filtern oder zu sortieren.

FireDAC kann auch nur maximal soviel Daten laden wie der SQL-Server hergibt. Wenn eine Query nur einen Record liefert, dann müssen das schon ziemlich viele und große Felder sein um 1 GB voll zu bekommen.

Evtl. ein Blob-Feld beteiligt.
Hatte auch mal eine Komponente deren Verhalten war: "Uh, da kommt bein Memo/Blob-Feld, schnell mal ein paar MB vorsichtshalber reservieren..."

hoika 10. Jul 2018 20:10

AW: FireDAC Query Speicher freigeben
 
Hallo,

dazu lese ich folgendes.

fmAll – Alle Rowsets werden automatisch direkt nach Ausführung der SQL-Anweisung abgerufen. Dies entspricht dem Aufruf der Methode FetchAll.

Hinweis: Nicht alle DBMSs unterstützen das Abrufen von Rowsets. FireDAC kann dies aber zulasten der Geschwindigkeit emulieren. Emuliertes Abrufen von Rowsets führt zu einer Geschwindigkeitsreduktion von 50 % im Vergleich zum tatsächlichen Abrufen.


Also ja, könnte am fmAll liegen.

Uwe Raabe 10. Jul 2018 20:38

AW: FireDAC Query Speicher freigeben
 
Zitat:

Zitat von hoika (Beitrag 1406893)
fmAll – Alle Rowsets werden automatisch direkt nach Ausführung der SQL-Anweisung abgerufen. Dies entspricht dem Aufruf der Methode FetchAll.

Wenn die Query nur einen Record zurückliefert, ist der FetchMode vollkommen egal.

haentschman 11. Jul 2018 07:38

AW: FireDAC Query Speicher freigeben
 
@Der schöne Günther:
Zitat:

Ich kann morgen noch einmal nachschauen was ich bei mir ändern musste damit er aufhört.
...bitte, bitte. 8-)

Der schöne Günther 11. Jul 2018 07:55

AW: FireDAC Query Speicher freigeben
 
Ich habe in der Versionsverwaltung meines Vertrauens zwei Dinge gefunden:

Zitat:

Wir entfernen die FireDAC-Indizes denn das scheint dafür zu sorgen dass FireDAC sich alles ins RAM schaufeln will (wofür auch immer)
  • Auf allen
    Delphi-Quellcode:
    TFDQuery
    und
    Delphi-Quellcode:
    TFDTable
    -Objekten explizit
    Delphi-Quellcode:
    IndexesActive = False
    gesetzt
  • Auf allen
    Delphi-Quellcode:
    TFDQuery
    und
    Delphi-Quellcode:
    TFDTable
    -Objekten evtl. vorhandene Werte für
    Delphi-Quellcode:
    IndexFieldNames
    entfernt


und


Zitat:

FetchOptions.RecsMax = 100 gesetzt für Tabelle profileValues da sonst ein
POST FireDAC veranlasste, die gesamte Tabelle in den Speicher zu laden
Hier wurde bei einer bestimmten Tabelle folgendes gesetzt:
Delphi-Quellcode:
+    FetchOptions.AssignedValues = [evRecsSkip, evRecsMax]
+    FetchOptions.RecsSkip = 0
+    FetchOptions.RecsMax = 100

Uwe Raabe 11. Jul 2018 09:57

AW: FireDAC Query Speicher freigeben
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1406905)
Wir entfernen die FireDAC-Indizes denn das scheint dafür zu sorgen dass FireDAC sich alles ins RAM schaufeln will (wofür auch immer)

Natürlich muss FireDAC alle Datensätze (also die von der Query gelieferten) im Speicher haben, damit sie lokal sortiert werden können. Wie sollte das auch sonst gehen. Das entspricht quasi einem FetchAll. Übrigens kann auch ein Aufruf von RecordCount unter bestimmten Umständen dieses auslösen.

Das erklärt aber nicht, warum eine Query, die einen einzigen Datensatz zurückliefert, über 1 GB Speicher benötigt.

Daher mein Vorschlag, die Query isoliert außerhalb des Programms bzw. in einem Testprogramm auszuführen. Entweder braucht sie dort auch diesen Speicher, dann muss man sehen, welche Felder das verursachen. Ist der Speicherverbrauch der Query selbst aber deutlich geringer, liegt das Problem innerhalb des Programms und man kann dann sukzessiv die übrige Funktionalität einbinden, bis der Auslöser für den enormen Speicherverbrauch gefunden ist.

haentschman 11. Jul 2018 13:52

AW: FireDAC Query Speicher freigeben
 
Zitat:

Das erklärt aber nicht, warum eine Query, die einen einzigen Datensatz zurückliefert, über 1 GB Speicher benötigt.
...richtig. :oops:
Lösung:
Die Form hat eine Datenmenge geöffnet, ohne WHERE, die NICHTS dieser Form zutun hatte. Die Datenmenge Tabelle Mail mit 35000 Datensätzen und reichlich großen Feldern und Blobs. (Ich tippe auf Copy/Paste Fehler meines Vorgängers) Das war aber so im Code versteckt...:? Nun haben wir mit 3500 Datensätzen in der Hauptdatenmenge (300 Felder) 450MB... Damit kann ich leben. :zwinker:

Sorry, das hatte ich nicht auf dem Schirm. :oops:

Danke an Alle. :kiss:

p80286 11. Jul 2018 20:37

AW: FireDAC Query Speicher freigeben
 
Zitat:

Der Zauberlehrling
Hat der alte Hexenmeister
sich doch einmal wegbegeben!
Und nun sollen seine Geister
auch nach meinem Willen leben.
Seine Wort und Werke
merkt ich und den Brauch,
und mit Geistesstärke
tu ich Wunder auch.
Walle! walle
Manche Strecke,
daß, zum Zwecke,
Wasser fließe
und mit reichem, vollem Schwalle
zu dem Bade sich ergieße.

Und nun komm, du alter Besen!
Nimm die schlechten Lumpenhüllen;
bist schon lange Knecht gewesen:
nun erfülle meinen Willen!
Auf zwei Beinen stehe,
oben sei ein Kopf,
eile nun und gehe
mit dem Wassertopf!

Walle! walle
manche Strecke,
daß, zum Zwecke,
Wasser fließe
und mit reichem, vollem Schwalle
zu dem Bade sich ergieße.

Seht, er läuft zum Ufer nieder,
Wahrlich! ist schon an dem Flusse,
und mit Blitzesschnelle wieder
ist er hier mit raschem Gusse.
Schon zum zweiten Male!
Wie das Becken schwillt!
Wie sich jede Schale
voll mit Wasser füllt!

Stehe! stehe!
denn wir haben
deiner Gaben
vollgemessen! -
Ach, ich merk es! Wehe! wehe!
Hab ich doch das Wort vergessen!

Ach, das Wort, worauf am Ende
er das wird, was er gewesen.
Ach, er läuft und bringt behende!
Wärst du doch der alte Besen!
Immer neue Güsse
bringt er schnell herein,
Ach! und hundert Flüsse
stürzen auf mich ein.

Nein, nicht länger
kann ichs lassen;
will ihn fassen.
Das ist Tücke!
Ach! nun wird mir immer bänger!
Welche Miene! welche Blicke!

O du Ausgeburt der Hölle!
Soll das ganze Haus ersaufen?
Seh ich über jede Schwelle
doch schon Wasserströme laufen.
Ein verruchter Besen,
der nicht hören will!
Stock, der du gewesen,
steh doch wieder still!

Willst am Ende
gar nicht lassen?
Will dich fassen,
will dich halten
und das alte Holz behende
mit dem scharfen Beile spalten.

Seht da kommt er schleppend wieder!
Wie ich mich nur auf dich werfe,
gleich, o Kobold, liegst du nieder;
krachend trifft die glatte Schärfe.
Wahrlich, brav getroffen!
Seht, er ist entzwei!
Und nun kann ich hoffen,
und ich atme frei!

Wehe! wehe!
Beide Teile
stehn in Eile
schon als Knechte
völlig fertig in die Höhe!
Helft mir, ach! ihr hohen Mächte!

Und sie laufen! Naß und nässer
wirds im Saal und auf den Stufen.
Welch entsetzliches Gewässer!
Herr und Meister! hör mich rufen! -
Ach, da kommt der Meister!
Herr, die Not ist groß!
Die ich rief, die Geister
werd ich nun nicht los.

"In die Ecke,
Besen, Besen!
Seids gewesen.
Denn als Geister
ruft euch nur zu diesem Zwecke,
erst hervor der alte Meister."

Johann Wolfgang von Goethe
:wall:

haentschman 12. Jul 2018 06:00

AW: FireDAC Query Speicher freigeben
 
...da sieht man man wieder. Ich hätte in der Schule besser aufpassen sollen. :oops:

Zu meiner Verteidigung:

Delphi-Quellcode:
if NOT(DMED.FDQBelKopf.Active) then
      DMED.FDQBelKopf.open();
    if NOT(DMED.FDQBelPos.Active) then
      DMED.FDQBelPos.open();
    if NOT(DMED.FDQBelArt.Active) then
      DMED.FDQBelArt.open();
    if NOT(DMED.FDQVorgang.Active) then
      DMED.FDQVorgang.open();
    if NOT(DMED.FDQTermin.Active) then
      DMED.FDQTermin.open();
    if NOT(DMED.FDQAdr.Active) then
      DMED.FDQAdr.open();
    if NOT(DMED.FDQEMail.Active) then
      DMED.FDQEMail.open(); // die hier
    if NOT(DMED.FDQTeil.Active) then
      DMED.FDQTeil.open();
    if NOT(DMED.FDQBelStatus.Active) then
      DMED.FDQBelStatus.open();
    if NOT(DMED.FDQZahlung.Active) then
      DMED.FDQZahlung.open();

    if NOT(DMLUP.FDQDatevPlus.Active) then
      DMLUP.FDQDatevPlus.open();
    if NOT(DMLUP.FDQDatevMinus.Active) then
      DMLUP.FDQDatevMinus.open();
...da kann man so etwas mal übersehen. 8-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:03 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