Delphi-PRAXiS
Seite 2 von 2     12   

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)

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 18:03 Uhr.
Seite 2 von 2     12   

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