Minutenlange Pause beim Drucken von VK-Rechnungen

4. April 2007 21:29

Tag Gemeinde,

ich hätt da mal gern ein Problem 8-)

Seit (wahrscheinlich) 4.0 SP3 gibt es in diversen Reports (z.B. Verkaufsrechnung (206), Verkaufsgutschrift (207)) eine Funktion "GenerateBufferFromValueEntry()" die bei vielen Wertposten offensichtlich meint, durchaus auch mal ein bis zwei Minuten auf dem FIND('-') ausharren zu müssen, sprich also sehr lange benötigt den ersten Datensatz zu finden (SQL). FirstValueEntry ist dabei 0. Lasse ich den SETFILTER auf die "Entry No." aus, dann geht das gewohnt schnell. Das Codefragment ist unten zu sehen.

Wieder mal ein SQL Server (2005) Problem? Kann das jemand nachvollziehen, bestätigen oder hat ggf. sogar eine SQL seitige Lösung?

Code:
TotalQuantity := SalesInvoiceLine2."Quantity (Base)";
ValueEntry.SETCURRENTKEY("Document No.","Posting Date");
ValueEntry.SETRANGE("Document No.",SalesInvoiceLine2."Document No.");
ValueEntry.SETRANGE("Posting Date","Sales Invoice Header"."Posting Date");
ValueEntry.SETRANGE("Item Charge No.",'');
ValueEntry.SETFILTER("Entry No.",'%1..',FirstValueEntryNo);
IF ValueEntry.FIND('-') THEN

5. April 2007 11:05

Hallo SilverX,

ich kenne mich mit dem SQL nicht so aus, aber ich denke durch eine Schlüsseloptimierung sollte es auch schneller gehen.

Du filterts auf dem Prim.Key (ValueEntry.SETFILTER("Entry No.",'%1..',FirstValueEntryNo);) aber der ist nicht im Schlüssel enthalten.
(ValueEntry.SETCURRENTKEY("Document No.","Posting Date");)

Versuch doch mal diesen mit einzubinden. Dann sollte es auch schneller gehen.

Hoschi Blume

5. April 2007 14:18

Die Funktion gibt es schon länger. Sie wurde eigentlich aufgrund von neuen deutschen gesetzlichen Vorschriften eingeführt, dass bei Rechnungen alle Lieferungen mit angedruckt werden müssen. Das wird aber selten so heiss gegessen , wie es hier gekocht wurde. Jeweils einzeln pro Rechnungszeile die Lieferungen erhöht nur unnötig den Paperverbrauch. Ersatzweise reicht meist auch das Andrucken aller Lieferscheinkopfnummern. Dann kann man diese Funktion komplett umgehen. Wenn mit Sammelrechnungen gearbeitet wird, ist diese ohnehin komplett überflüssig, da dann die Rechnungszeilen schon alle notwendigen Informationen bereitstellen.

Wenn man sie unbedingt braucht, wäre beim SQL-Server das Verwenden von FINDFIRST bzw. bei dieser Funktion FINDSET statt FIND('-') immer anzuraten.

5. April 2007 14:21

Hi!

Interessant wäre es hier zu wissen, was denn dem FIND folgt ...

Wird nur geprüft, ob überhaupt ein DS gefunden wird, dann sollte ISEMPTY verwendet werden.
Wird nur der erste DS verwendet, dann sollte FINDFIRST verwendet werden.
Soll ein Resultset bearbeitet werden, dann sollte FINDSET verwendet werden; FINDSET(TRUE, FALSE) wenn das Set modifiziert wird.

Des Weiteren wird auf "Item Charge No." gefiltert, das wahrscheinlich nicht Bestandteil eines (SQL) Indexes ist ...

P.S.: Die "Entry No." ist implizit schon im Index vorhanden, das dies den Clustered Index definiert; die Referenz darauf ist in jedem Non-Clustered Index enthalten.

5. April 2007 14:31

stryk hat geschrieben:Interessant wäre es hier zu wissen, was denn dem FIND folgt ...

Es folgt eine REPEAT-UNTIL Schleife, die anhand der Artikelposten, die zu den gefundenen Wertposten gehören, den Verkaufslieferungspuffer (Tabelle 7190) füllt.

5. April 2007 14:53

Das Problem ist ja nicht das Umgehen der Funktion oder das optimieren.

Interessant in dem Zusammenhang ist, dass es tatsächlich nur 2-3 Datensätze betrifft die durch das zusätzliche Filtern der "Entry No." dann minutenlang für den FIND brauchen. Unabhängig davon, ob der Key nun bis auf die letzte Stelle 100% passt, sollte der Abfrageoptimierer hier schon bemerken, dass der weitere Filter hier beinahe keine Rolle mehr spielt...

5. April 2007 15:51

Wie sieht das denn im SQL Profiler aus, wenn die Abfrage soz. "hängt"?
Lange "Duration", viele "Reads"? Der Ausführungsplan wäre ebenso interessant ...
(sorry, kann im Moment nicht selber testen ...)

5. April 2007 16:16

zu

P.S.: Die "Entry No." ist implizit schon im Index vorhanden, das dies den Clustered Index definiert; die Referenz darauf ist in jedem Non-Clustered Index enthalten.

dann würde es doch mehr sinn machen den Key gleich als erstes zu setzten und nicht als letztes.

Code:
TotalQuantity := SalesInvoiceLine2."Quantity (Base)";
ValueEntry.SETCURRENTKEY("Document No.","Posting Date");
ValueEntry.SETFILTER("Entry No.",'%1..',FirstValueEntryNo);
ValueEntry.SETRANGE("Document No.",SalesInvoiceLine2."Document No.");
ValueEntry.SETRANGE("Posting Date","Sales Invoice Header"."Posting Date");
ValueEntry.SETRANGE("Item Charge No.",'');

IF ValueEntry.FIND('-') THEN


Gruß und schöne Feiertage Hoschi Blume

6. April 2007 11:29

Die Reihenfolge der Filterung ist mit SQL Server egal - im Gegensatz zu "native". Die Abfrage wird erst mit dem FIND an den Server gesendete, dabei werden alle Filter zu einer WHERE Clausel zusammengefasst, und SQL Server behandelt alle WHERE Teile gleichberechtigt ...

6. April 2007 21:04

Den Profiler werd ich mal am Dienstag drüber laufen lassen.