Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi FireDAC + Firebird dynamisch optimieren (https://www.delphipraxis.net/174898-firedac-firebird-dynamisch-optimieren.html)

stahli 16. Mai 2013 22:32

Datenbank: Firebird • Version: 2.5.2 • Zugriff über: FireDAC

FireDAC + Firebird dynamisch optimieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Bei meinen ersten Versuchen mit FireDAC habe ich einen kleinen ORM von IBX umgestellt.

Das lief (abgesehen von anderen Problemen) auch recht langsam. Ich habe bisher erst mal nur eine AdQuery, die immer neu geöffnet und geschlossen wird.
Da ist also noch nichts optimiert. Trotzdem ging das auf die Art unter IBX flinker.

Was sollte man grundsätzlich beachten, damit der ORM möglichst flott läuft?

Der AQTime-Profiler zeigt den AdTimerPool als Zeitfresser an. Ich gehe aber eher davon aus, dass der parallel läuft - stimmt das?
Ich bin in dem Bereich Neuling und kann schlecht einordnen, worauf man achten sollte.

Da der ORM natürlich "im Stillen" laufen soll, möchte ich die Cursoränderung und GUI-Bremse möglichst vermeiden.
Auf die Komponente ADGUIxWaitCursor kann man wohl nicht verzichten? Offenbar kann man aber SreenCursor auf gcrNone setzen (kann ich gerade nicht testen).
Wird wohl einige Zeit brauchen, bis ich das Konzept verstehe...

QuickAndDirty 18. Mai 2013 10:03

AW: FireDAC + Firebird dynamisch optimieren
 
hast du für einfache* Queries, Pingpongs von weit über 125 ms?

*nur eine Tabelle
und Abfrage auf einen nicht-kombinierten-Schlüssel
und kein order by (asc,desc)entgegen der schlüssel Reihenfolge
und ca 100 Datensätze in der Ergebnismenge

stahli 19. Mai 2013 21:30

AW: FireDAC + Firebird dynamisch optimieren
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hmm, offenbar liegt das Problem in der GUI-Syncronisation oder so...!?

Die Abfragen selbst laufen ohne erkennbare Verzögerung ab. Jedenfalls ist beim debugen keine Verzögerung zu bemerken und AQTime gibt in den relevanten Funktionen, die die SQL-Statements durchführen nur Sekundenbruchteile an.

Der Zellenwechsel innerhalb des Gitters dauert ca. 8 Sekunden. Dabei werden zwar die Zellen neu mit Inhalten versorgt, aber die Dauer liegt offenbar nicht an der Datenbeschaffung selbst.

Zum Neuzeichnen des Formulars und seiner datengebundenen Controls starte ich einen Thread, der dann das entsprechende Formular syncronisiert zum Mainthread neu zeichnet.

Nutze ich Objektlisten zur Datenspeicherung geht alles sehr fix. Kommt aber FireDac in´s Spiel (über einen ORM), dann wird das so langsam.
Ich werde das jetzt mal analog über IBX umsetzen, mal schauen wie das dann aussieht.

Ich schätze, dass FireDac sich auch irgendwie mit der FMX-GUI syncronisieren will und dadurch die Verzögerung entsteht.

Vermutlich ist das Problem sehr speziell (da FireDac in einem FMX-Framework eingesetzt wird) aber vielleicht hat ja jemand doch eine Idee...

QuickAndDirty 19. Mai 2013 22:16

AW: FireDAC + Firebird dynamisch optimieren
 
vcl gitter greifen auf recordcount oder recno zu, ich glaube das war damals ein problem. Ich weiß nicht was wir gemacht haben aber man kann das verhalten im query einstellen.

stahli 21. Mai 2013 12:14

AW: FireDAC + Firebird dynamisch optimieren
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ich habe soeben in meiner unendlichen Weisheit festgestellt, dass es sinnvoll sein kann, vernünftige Indizes zu definieren. :oops: ;-)

Bei 30T Datensätzen dauert es dennoch einen Moment, "select Count" abzuhandeln.

Ich muss dann halt wohl das Ergebnis zwischenpuffern und nur in bestimmten Fällen neu ermitteln. Wenn ich die Rückgabe per fester Vorgabe regle, dann läuft das ausreichend schnell.

Ich will diese "Optimierungen" letztlich aber meinem Framework und insbesondere meinem Gitter überlassen, so dass sich der Programmierer dann nicht mehr darum kümmern muss.
Gefühlt bindet man einfach die 1Mio Objekte bzw. Datensätze an das Gitter und das Framework beschafft dann die aktuell benötigten (weil gerade sichtbaren) Datensätze. Das funktioniert dann für diverse Listen und Datenmengen gleichermaßen.

Geringe Leistungseinbußen will ich dann zu Gunsten der effektiven Handhabung in Kauf nehmen.
Anbei mal die Count-Funktionen der beiden aktuellen ORM-Varianten (IBX + FireDAC) und die AQTime-Logs. Das muss natürlich jetzt noch gesäubert werden.


Delphi-Quellcode:
function TssOrmAd.ListItemsCount(O: TObject): Integer;
var
  TableName: string;
begin
  //  Exit(33901); // Simulation

  if not(O is TssObject) then
    Exit(0);
  if (O as TssObject).SaveMode then
    Exit(0);

  TableName := 'ItemsList';

  AdQuery.SQL.Clear;
  AdQuery.SQL.Add('select Count(*) from ' + TableName);
  AdQuery.SQL.Add('where Owner = :Owner');
  AdQuery.ParamByName('Owner').AsString := (O as TssObject).Id;
  AdQuery.Open;
  Result := AdQuery.FieldByName('Count').AsInteger;
  AdQuery.Close;
end;

...

function TssOrmIbx.ListItemsCount(O: TObject): Integer;
var
  TableName: string;
begin
  //  Exit(33901); // Simulation

  if not(O is TssObject) then
    Exit(0);
  if (O as TssObject).SaveMode then
    Exit(0);
  if IBSQL.Open then
    Exit(0);

  TableName := 'ItemsList';

  IBSQL.SQL.Clear;
  IBSQL.SQL.Add('select Count(*) from ' + TableName);
  IBSQL.SQL.Add('where Owner = :Owner');
  IBSQL.ParamByName('Owner').AsString := (O as TssObject).Id;
  IBSQL.ExecQuery;
  Result := IBSQL.FieldByName('Count').AsInteger;
  IBSQL.Close;
end;

QuickAndDirty 24. Mai 2013 09:12

AW: FireDAC + Firebird dynamisch optimieren
 
Also wenn ich das richtig verstanden habe machst du selbst datensensitive Gitter.
Ich würde mich von einer Count-Funktion verabschieden.
Die Gitter sollten sich so verhalten wie alle anderen datensensitiven Gitter die auf Queries arbeiten auch:
Der Laufbalken hat nur 3 Zustände oben, unten, in der mitte.

Benutzt man in Firemonkey auch diese Struktur?
TFMGRID <-> TGridDatalink <-> TDatasource <-> TQueryDataLink <-> TADQuery
oder macht es das anders?

Wenn du einfach mal ganze Tabellen "öffnen" können willst. Würde ich auf dem TADtable arbeiten, das macht das ganze caching usw. schon so intelligent wie möglich. (Livewindow,Recordcount &c.)

stahli 24. Mai 2013 11:35

AW: FireDAC + Firebird dynamisch optimieren
 
Ich habe ein eigenes Gitter und eine eigene Listbox, die an diverse Datenmengen gebunden werden können:

- an eine dumme TObjectList
- an eine dumme TIBQuery oder TAdQuery (optional an andere DataSets)
- an eine TssList, die dynamisch von meinem Framework bereitgestellt und gefüllt wird (z.B. TAbfallMain.GrundstueckList)

Die TssList kann ihre Daten wiederum
- in generischen Listen oder
- über einen ORM (aktuell IBX-FireBird, FireDAC-FireBird) verwalten.

TDataLink und ähnliche Controls benutze ich nicht.

Die Anzahl der Datensätze will ich immer wissen da das Grid schon scrollen soll, wenn man in die Nähe des Gitter-Randes kommt. So soll man beim scrollen nach oben und unten schon immer einige der nächsten Datensätze sehen. Standardmäßig ist ein Scroll-Rand von 20% der Gitterhöhe eingestellt. Dazu muss das Gitter aber wissen, wie viele Datensätze noch zur Verfügung stehen.

Die TssList kapselt sämtliche Verhaltensweisen intern auf die unterschiedlichen Datenspeicherarten weg. Insofern soll die TssList immer Auskunft geben können, wie viele Datensätze bzw. Objekte sie gerade representiert.

Bei der Speicherung der Daten in generischen Listen ist die Abfrage ja jederzeit ohne zeitliche Verzögerung möglich.
Bei Einsatz eines ORM frage ich die Anzahl über "Select Count(*)" ab und merke mir das Resultat bis Änderungen der Datenmenge vorgenommen werden.

Das funktioniert jetzt sehr gut und m.E. auch schnell genug.
-> http://www.delphipraxis.net/1216265-post20.html


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