Performance mit Findfirst

14. November 2018 07:54

Ich habe eine Page welche eine Temp-Tabelle als Source verwendet und diese wird mit der Funktion Dateneinlesen befüllt.

Darin gibt es eine Funktion InProdPlanungCheck, welche für jeden erstellten Datensatz ausgeführt wird.
Und diese Funktion bremst ziemlich. Ohne diese Funktion dauert der Start der Page ca. 10 Sekunden und mit ca. 30 Sekunden.
Anbei der Code der Funktion
Code:
ProdPlanungFAVerursZeilen.RESET;
ProdPlanungFAVerursZeilen.SETCURRENTKEY("Herkunftsbelegnr.","Herkunftsbelegzeilennr.","Artikelnr.",Arbeitsplatzgruppe);
ProdPlanungFAVerursZeilen.SETRANGE("Herkunftsbelegnr.",Auftragsnr);
ProdPlanungFAVerursZeilen.SETRANGE("Herkunftsbelegzeilennr.",Zeilennr);
ProdPlanungFAVerursZeilen.SETRANGE("Artikelnr.",Artikelnr);
ProdPlanungFAVerursZeilen.SETRANGE(Arbeitsplatzgruppe,Arbeitsplatz);
IF ProdPlanungFAVerursZeilen.FINDFIRST THEN BEGIN
  IF FertigungsauftragProduktion.Status <> FertigungsauftragProduktion.Status::Beendet THEN BEGIN
    Planungsstatusint := 1;
    Fertigungsauftragsnr := ProdPlanungFAVerursZeilen."Prod.Planung FA Nr.";
  END;
END ELSE BEGIN
  Planungsstatusint := 0;
  Fertigungsauftragsnr := '';
END;

Die Tabelle ProdPlanungFAVerusZeilen hat den Key, welcher bei Setcurrentkey verwendet wird.
Wenn ich den Block ab FINDFIRST wegnehme dann ist es wieder schnell.
Was könnte ich hier besser machen??

Danke und lg
stony

Re: Performance mit Findfirst

14. November 2018 11:14

Hallo Stony.

Warum machst du das Setcurrentkey ?
Wenn du es nicht auf eine besondere Sortierung abgesehen hast, solltest du den SQL-Server immer selbst wählen lassen.

Ohne das Findfirst (und alles danach) guckt er die gefilterten Daten nie an also macht er im wesentlichen nichts was dann auch schneller sein müsste.

Re: Performance mit Findfirst

14. November 2018 11:29

Das mit Setcurrentkey habe ich so nicht gewusst.

Habe es nun ausgebaut aber leider wird es nicht schneller.

Alle Felder im Setrange sind als sekundär Key angelegt.

Re: Performance mit Findfirst

14. November 2018 11:39

Probier mal im SQL-Profiler diese Abfrage mitzuschneiden wenn du die Page öffnest.

Es gibt meistens 2 Szenarios.
A) Es ist eine große langsame abfrage
B) Es sind viele kleine, die sich summieren

Je nachdem wie du diese Funktion aufrufst, ist es also denkbar das die Abfrage einzeln betrachtet schnell genug ist.

Re: Performance mit Findfirst

14. November 2018 17:24

Du könntest alles ab dem IF noch in ein IF NOT ISEMPTY() kapseln. Aber so richtig viel wird das wohl auch nicht bringen.

Kannst du die FA Nr. ggf. über ein FlowField in der Tabelle ermitteln? Ich denke das wäre die schnellste Variante.

Re: Performance mit Findfirst

14. November 2018 17:48

Hallo,

die Felder, auf die du ein SETRANGE machst, sind doch keine Flowfields oder?

Gruß Fiddi

Re: Performance mit Findfirst

14. November 2018 18:21

fiddi hat geschrieben:die Felder, auf die du ein SETRANGE machst, sind doch keine Flowfields oder?
Lass mal den Teufel von der Wand :-)

Re: Performance mit Findfirst

15. November 2018 07:36

Ich weiß zwar nicht genau wie deine Temp-Tabelle für die Page aufgebaut ist, aber du könntest versuchen die Daten mit einem Query zu ermitteln und dann in die Temp-Tabelle schreiben.
Das hat uns in solchen Fällen immer ordentlich Performance raus geholt.

Re: Performance mit Findfirst

27. November 2018 11:34

stony hat geschrieben:Die Tabelle ProdPlanungFAVerusZeilen hat den Key, welcher bei Setcurrentkey verwendet wird.


Dann nimm doch:
Code:
if ProdPlanungFAVerursZeilen.get(Auftragsnr,Zeilennr,Artikelnr,Arbeitsplatz) then begin
  IF FertigungsauftragProduktion.Status <> FertigungsauftragProduktion.Status::Beendet THEN BEGIN
    Planungsstatusint := 1;
    Fertigungsauftragsnr := ProdPlanungFAVerursZeilen."Prod.Planung FA Nr.";
  END;
END ELSE BEGIN
  Planungsstatusint := 0;
  Fertigungsauftragsnr := '';
END;


Wird jetzt aber auch nicht soo viel bringen.

Wenn ich mal nur den Teilbereich betrachte, dann würde ich das ganz anders machen. Das kann aber gegen die Logik der Programmierung um deinen Ausschnitt herum sein. Zumindest kann ich so nicht erkenn, ob es vielleicht Sinnvoler ist, den Datensatz nur dann abzurufen, wenn FertigungsauftragProduktion.Status nicht beendet ist. Das würde so aussehen und bringt dir bestimmt etwas an Geschwindigkeit:
Code:
Planungsstatusint := 0;
Fertigungsauftragsnr := '';
IF FertigungsauftragProduktion.Status <> FertigungsauftragProduktion.Status::Beendet THEN //Nur wenn der Status nich Beendet ist, hole die Produnktionsplanungsnr.
  if ProdPlanungFAVerursZeilen.get(Auftragsnr,Zeilennr,Artikelnr,Arbeitsplatz) then begin
    Planungsstatusint := 1;
    Fertigungsauftragsnr := ProdPlanungFAVerursZeilen."Prod.Planung FA Nr.";
  END;


Achso: Bei 10 Sekunden Wartezeit bis eine Page aufgeht, würde ich das Ganze umstrukturieren (falls möglich) und ggf. auf die Nutzung temporärer Tabellen verzichten. Wir haben hier eine Archivlösung, welche alle archivierten Datensätze eines Debitoren/Kreditoren in einer FactBox anzeigt. Die FactBox füllt die Daten auch On-the-fly in eine temporäre Tabelle. Mittlerweile gibt es Kunden, da muss man ein paar Sekunden warten, wenn man diese in der Liste anklickt. Das sollte man so nicht machen. (Meine Meinung)