gelöst Performance Problem


Getting started ... Alles für einen gelungenen Start.

Moderatoren: Jan, Steff

gelöst Performance Problem

Beitragvon ChrissixD » 26.09.2017, 08:13

Hallo zusammen,
ich habe zurzeit ein Performance Problem und ich hoffe ihr könnt mir da helfen.
Also ich habe in einem Select eine Lieferantennummer. Diese Nummer kann in einem Material hinterlegt sein (in MARA).
Jetzt soll ich prüfen ob ein Material mit der aktuellen Lieferantennummer in der Tabelle MARC ein bestimmtes Dispomerkmal hat (VI).
Zurzeit habe ich es so gelöst:

Code: Alles auswählen
select single MARC~DISMM into WA-DISPO
        from MARC inner join MARA on MARC~MATNR = MARA~MATNR
        where MARA~/FIS/V_DTN_LIFNR = WA-KUNNR and
              MARC~DISMM = 'VI'.
      if SY-SUBRC = 0.
         ...
 


Es soll nur geprüft werden ob dieses Dipsomerkmal VI vorhanden ist, aber durch diesen Code dauert es bei mehreren Lieferanten ewig. Gibt es noch eine andere Möglichkeit das abzufragen, welche performanter ist und die ich nicht sehe?

Gruß
ChrissixD
ForumUser
 
Beiträge: 26
Registriert: 01.03.2017, 08:05
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Sponsor

Alte ABAP-Entwicklerweisheit: Weißt du weder aus noch ein, baust du einen BADI ein

Re: Performance Problem

Beitragvon DeathAndPain » 26.09.2017, 09:39

Na ja, Du gibst Deinem SELECT den Anschein, als ob Du auf der MARC suchen würdest. Tatsächlich suchst Du aber auf der MARA. Bei einer Joinbedingung würde ich auf der linken Seite immer ein Feld der gejointen Tabelle angeben und auf der rechten Seite dann ein Feld der Ausgangstabelle (oder bei Kettenjoins einer zuvor gejointen Tabelle).

Stellt man Deinen SELECT nach diesen Grundsätzen um, so sieht er - ergebnisgleich - so aus:

Code: Alles auswählen
SELECT SINGLE MARC~DISMM INTO WA-DISPO
  FROM MARA
  JOIN MARC ON MARC~MATNR = MARA~MATNR
 WHERE MARA~/FIS/V_DTN_LIFNR = WA-KUNNR
   AND MARC~DISMM = 'VI'.

Hier sieht man schon ein Stück deutlicher, was passiert: Du durchsuchst die MARA nach dem Feld /FIS/V_DTN_LIFNR, und für alle gefundenen Materialien durchsuchst Du dann noch die MARC. Problem an der Sache: Die MARA hat auf dem Feld /FIS/V_DTN_LIFNR, mit dem Deine Suche beginnt, keinerlei Index. (Nebenbei hat die MARC auf dem Feld DISMM auch keinen Index, aber das ist von untergeordneter Bedeutung, solange dasselbe Material bei euch nicht in sehr vielen Werken vorkommt, denn Du hast ja immerhin das Primärschlüsselfeld MARC~MATNR spezifiziert).

Die Frage ist nun, ob Du eine Alternative dazu hast, über ein indiziertes Feld anstatt über /FIS/V_DTN_LIFNR zu suchen. Wenn Deine Programmlogik letzteres zwingend erfordert, dann hast Du zwei Möglichkeiten:

a) Du kannst eine interne Tabelle als SORTED oder HASHED TABLE mit den Feldern MATNR und /FIS/V_DTN_LIFNR anlegen und dann einen SELECT ohne WHERE-Bedingung auf die MARA in diese Tabelle machen. Schlüssel der Tabelle muss /FIS/V_DTN_LIFNR sein. Dadurch pufferst Du die relevanten Felder der MARA in dieser Tabelle (also effektiv im Hauptspeicher) zwischen und kannst anschließend anstelle Deines JOINs alle weiteren Suchen auf dieser internen Tabelle machen. Dann hast Du einmal zu Programmstart einen langsamen SELECT, suchst danach aber hochperformant im Hauptspeicher. Natürlich hast Du auch eine gewisse Hauptspeicherbelegung dadurch, weswegen ich nur diese beiden Spalten angeben würde und nicht etwa die ganze MARA per SELECT * puffern würde.

b) Du gehst in die SE11 und legst auf der MARA einen Datenbankindex auf dem Feld /FIS/V_DTN_LIFNR an. Dies ist nicht als verwerfliche Modifikation einzuschätzen, da Du die Tabelle ja nicht änderst und mit dem SAP-Standardcode daher nicht in Konflikt gerätst. Lediglich in sehr seltenen Fällen könnte es sein, dass der Standardcode auch einen SELECT enthält, der das Feld /FIS/V_DTN_LIFNR enthält, und der dann Deinen statt des Indexes benutzt, den er sonst verwendet hätte. Wenn für jenen SELECT Dein Index dann weniger performant sein sollte, dann hättest Du an den Stellen im Code eine schlechtere Systemperformance. Da müsstest Du aber viel Pech haben, damit Dir das passiert, da der Datenbankoptimierer den zu verwendenden Index ziemlich clever auszuwählen pflegt und nur selten danebengreift.

Nebenbei sollte Dir klar sein, dass Du als Ergebnis in WA-DISPO immer 'VI' zurückbekommen wirst, da Du dies ja in der WHERE-Schleife explizit forderst. Der SELECT taugt also nur dazu, über SY-SUBRC zu prüfen, ob es solch ein Material überhaupt gibt oder nicht.

Für diese Nachricht hat DeathAndPain einen Dank bekommen :
ChrissixD
DeathAndPain
Specialist
 
Beiträge: 308
Registriert: 05.05.2006, 10:14
Dank erhalten: 79 mal
Ich bin: Entwickler/in

Re: Performance Problem

Beitragvon ChrissixD » 26.09.2017, 10:56

Hallo DeathAndPain,
danke mal wieder für deine ausführliche Antwort :)

Mit der Möglichkeit a) werde ich mich mal auseinandersetzen, aber in die Tabelle selber möchte ich erstmal nicht eingreifen (was du bei b beschrieben hast).

Nebenbei sollte Dir klar sein, dass Du als Ergebnis in WA-DISPO immer 'VI' zurückbekommen wirst, da Du dies ja in der WHERE-Schleife explizit forderst. Der SELECT taugt also nur dazu, über SY-SUBRC zu prüfen, ob es solch ein Material überhaupt gibt oder nicht.

Ja genau das soll es ja auch tun, ich muss wissen ob ein Material, zu diesem Lieferanten mit diesem Dispomerkmal existiert. Dabei ist egal welches Material oder sonst was, deswegen frage ich danach mit subrc ab, ob was gefunden wurde.

Danke nochmal und Gruß
ChrissixD
ForumUser
 
Beiträge: 26
Registriert: 01.03.2017, 08:05
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Re: Performance Problem

Beitragvon DeathAndPain » 26.09.2017, 11:12

aber in die Tabelle selber möchte ich erstmal nicht eingreifen (was du bei b beschrieben hast)

Es ist kein Eingriff in die Tabelle. Du fügst nur einen Suchindex hinzu. Ich bin gar nicht sicher, ob das bei einem Upgrade überhaupt als Modifikation hochkommen würde. Unkritisch wäre es auf jeden Fall.

Wenn Dir a) reicht, der Programmstart also nicht zu lange dauert (hängt von der Zahl eurer Materialien ab), ist das aber auch eine gute Lösung. Bei derartigen SELECTs ist es wichtig, dass sie nicht mehr als einmal pro Programmausführung vorkommen, da sie von vorne nach hinten durch die ganze Tabelle rasen und jeden einzelnen Eintrag anschauen müssen.

Ja genau das soll es ja auch tun, ich muss wissen ob ein Material, zu diesem Lieferanten mit diesem Dispomerkmal existiert. Dabei ist egal welches Material oder sonst was, deswegen frage ich danach mit subrc ab, ob was gefunden wurde.

Ich lese für solche Zwecke immer das Feld MANDT. Das gibt es so ziemlich in jeder Tabelle, und damit machst Du jedem, der Deinen Code später liest (Dich selbst eingeschlossen) deutlich, dass Dich der Wert nicht interessiert.

Für diese Nachricht hat DeathAndPain einen Dank bekommen :
ChrissixD
DeathAndPain
Specialist
 
Beiträge: 308
Registriert: 05.05.2006, 10:14
Dank erhalten: 79 mal
Ich bin: Entwickler/in

Re: Performance Problem

Beitragvon black_adept » 26.09.2017, 11:43

DeathAndPain hat geschrieben:Ich lese für solche Zwecke immer das Feld MANDT. Das gibt es so ziemlich in jeder Tabelle, und damit machst Du jedem, der Deinen Code später liest (Dich selbst eingeschlossen) deutlich, dass Dich der Wert nicht interessiert.
Interessant - ich verwende für so einen Zweck Kommentare.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 2725
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 397 mal
Ich bin: Freiberufler/in

Re: Performance Problem

Beitragvon ChrissixD » 26.09.2017, 11:48

Ich lese für solche Zwecke immer das Feld MANDT. Das gibt es so ziemlich in jeder Tabelle, und damit machst Du jedem, der Deinen Code später liest (Dich selbst eingeschlossen) deutlich, dass Dich der Wert nicht interessiert.


Das macht Sinn, da habe ich in dem Moment garnicht dran gedacht, dass man auch einfach andere Felder nehmen kann.
Gibt es denn nicht eine Abfrage, die zurückgibt ob etwas gefunden wurde oder nicht, ohne etwas in ein Feld schreiben zu müssen?
ChrissixD
ForumUser
 
Beiträge: 26
Registriert: 01.03.2017, 08:05
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Re: Performance Problem

Beitragvon ChrissixD » 26.09.2017, 11:49

@black_adept Wie meinst du das mit Kommentaren?
ChrissixD
ForumUser
 
Beiträge: 26
Registriert: 01.03.2017, 08:05
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Re: Performance Problem

Beitragvon DeathAndPain » 26.09.2017, 12:32

black_adept hat geschrieben:Interessant - ich verwende für so einen Zweck Kommentare.

Kommentieren kannst Du, so viel Du magst, aber Du wirst nicht umhin kommen, dem SELECT ein Feld mitzugeben, das er lesen soll. Und anstelle da irgendein Feld reinzuschreiben und dann eine Kommentarzeile hinzuzufügen, die dem Leser mitteilt, dass Du dieses Feld in Wahrheit doch nicht wissen willst, finde ich es schöner, das offensichtlich nutzlose Feld MANDT zu lesen (am besten in eine Dummyworkarea). Wenn danach dann gleich eine Prüfung auf SY-SUBRC kommt, sollte jedem minimal kompetenten Leser klar sein, was der Zweck der Übung ist.

Chrissi hat geschrieben:Gibt es denn nicht eine Abfrage, die zurückgibt ob etwas gefunden wurde oder nicht, ohne etwas in ein Feld schreiben zu müssen?

Du kannst SELECT COUNT( * ) schreiben, ohne ein INTO anzugeben. Dann kannst Du auch SY-SUBRC auswerten. Ohne es gemessen zu haben, halte ich das aber für langsamer, weil die Datenbank dann die Anzahl der Vorkommen zählt und nicht nach dem ersten Fund aufhört, obwohl Dich ja nur interessiert, ob es überhaupt einen gibt.

Für diese Nachricht hat DeathAndPain einen Dank bekommen :
ChrissixD
DeathAndPain
Specialist
 
Beiträge: 308
Registriert: 05.05.2006, 10:14
Dank erhalten: 79 mal
Ich bin: Entwickler/in

Re: Performance Problem

Beitragvon Daniel » 28.09.2017, 11:17

Ich verwende für die Existenz-Prüfung ziemlich konsequent den Select Count.
Wenn der Schlüssel einigermaßen brauchbar ist wird nur auf den Index und
nicht auf die Rumpftabelle zugegriffen. Das macht die Sache performant.
Es werden keine Daten sinnlos übertragen. Jedem der das liest ist sofort klar
was da passiert.
Die Prüfung muss aber auf SY-DBCNT gehen, SY-SUBRC ist immer null.
Daniel
Specialist
 
Beiträge: 208
Registriert: 10.09.2003, 13:20
Wohnort: Bielefeld
Dank erhalten: 15 mal

Re: Performance Problem

Beitragvon DeathAndPain » 28.09.2017, 13:13

Wenn der Schlüssel einigermaßen brauchbar ist wird nur auf den Index und nicht auf die Rumpftabelle zugegriffen. Das macht die Sache performant.

Das hängt von den Umständen ab. Du suchst vielleicht auf der MARC und kennst neben der Materialnummer nur ein nicht indiziertes Feld. Solch Suche wird nicht unvertretbar lange dauern, da es nicht endlos viele Werke geben wird, aber dennoch verschenkst Du Performance, da Dich ja nur die Existenz interessiert, der Interpreter aber nach der ersten Fundstelle in den anderen Werken weitersucht.

Es werden keine Daten sinnlos übertragen.

Ich halte das Übertragen des Mandanten, also eines dreistelligen Characterfeldes, für laufzeittechnisch vernachlässigbar und damit performanter als das häufige Weitersuchen nach dem Auffinden einer Fundstelle. Müsste man mal ein Testprogrämmchen schreiben, das die Laufzeiten vergleicht.

Jedem der das liest ist sofort klar was da passiert.

Die Idee, stattdessen MANDT zu lesen, stammt nicht von mir, sondern ich habe es im Programm eines anderen gelesen und sofort verstanden, was der Zweck war. Der Ansatz hat mir gefallen, und so habe ich ihn übernommen. Von daher behaupte ich, dass das genauso gut verständlich ist. Bei mir fragt man sich, was ich mit dem Mandanten will, bei Dir, warum Du da zählst. Einem halbwegs kompetenten Programmierer sollte aber in beiden Fällen sofort klar werden, was Sache ist.

Die Prüfung muss aber auf SY-DBCNT gehen, SY-SUBRC ist immer null.

Da liegst Du falsch, und nicht erst seit 7.40.
DeathAndPain
Specialist
 
Beiträge: 308
Registriert: 05.05.2006, 10:14
Dank erhalten: 79 mal
Ich bin: Entwickler/in

Re: Performance Problem

Beitragvon Daniel » 28.09.2017, 14:23

Zu dem Material existieren mehrere Werke.

Code: Alles auswählen
GET RUN TIME FIELD t0.

SELECT SINGLE mandt FROM marc INTO sy-mandt
       WHERE matnr EQ '9588188'
       AND   beskz EQ 'X'.

GET RUN TIME FIELD t1.

SELECT COUNT( * ) FROM marc
       WHERE matnr EQ '9588188'
       AND   beskz EQ 'X'.

GET RUN TIME FIELD t2.

te = t1 - t0.
WRITE: / te.
te = t2 - t1.
WRITE: / te.
 


    2.932
    2.292

Die Prüfung muss aber auf SY-DBCNT gehen, SY-SUBRC ist immer null.

Da liegst Du falsch, und nicht erst seit 7.40.

Stimmt. Das war aber nicht immer so, deshalb hab ich mir DBCNT angewöhnt.
Daniel
Specialist
 
Beiträge: 208
Registriert: 10.09.2003, 13:20
Wohnort: Bielefeld
Dank erhalten: 15 mal

Re: Performance Problem

Beitragvon DeathAndPain » 28.09.2017, 14:52

Ich konnte Deine Ergebnisse inhaltlich nachstellen, jedoch auch den Fehler finden: Der zweite SELECT ist im Vorteil, da er auf exakt denselben Schlüssel erfolgt und insofern durch den ersten SELECT ausgelöste Pufferungseffekte nutzen kann. Diese werden schon von der Datenbank erzeugt, egal ob die Tabelle in SAP als gepuffert eingestellt ist oder nicht.

Glaube nie einer Statistik, die Du nicht selbst gefälscht hast. (Churchill) :-D

Aufdecken kannst Du das leicht, indem Du in Deinem Code die beiden SELECTs vertauschst, so dass der COUNT( * ) zuerst kommt. Dann ist der MANDT schneller.

Außerdem musst Du den Report mehrmals starten, um Schwankungen und Einmaleffekte durch andere Dinge, die sich zeitgleich auf dem Server zutragen, herauszumitteln.

In diesem Beispiel (ich maß mit 9 Treffern auf das erste Primärschlüsselfeld, von denen ein Treffer dann auch das nicht indizierte zweite Feld getroffen hat) scheinen die tatsächlichen Performanceunterschiede der beiden Varianten im Bereich der Messungenauigkeit zu liegen, also näherungsweise gleich zu sein. Es dürfte aber klar sein, dass Dein Ansatz langsamer wird, je mehr zum im WHERE angegebenen Schlüsselteil passende Fundstellen es gibt, wohingegen mein Ansatz da besser skaliert, da er all diese Fundstellen nur in dem Fall durchsuchen muss, dass es keinen der Suchbedingung entsprechenden Wert auf der Datenbank gibt.
DeathAndPain
Specialist
 
Beiträge: 308
Registriert: 05.05.2006, 10:14
Dank erhalten: 79 mal
Ich bin: Entwickler/in

Re: Performance Problem

Beitragvon Daniel » 28.09.2017, 15:04

DeathAndPain hat geschrieben:Aufdecken kannst Du das leicht, indem Du in Deinem Code die beiden SELECTs vertauschst, so dass der COUNT( * ) zuerst kommt. Dann ist der MANDT schneller.

Weil der Wert dann besser gepuffert ist.
Ganz ehrlich, bei den Mini-Zeiten sind wir an der Grenze
des Meßbaren und inhaltlich ist es eigentlich auch egal.
Wobei hier noch ein Feld ausgewählt ist das nicht im Index
liegt. Nur mit MATNR auf MARA verschiebt sich das weiter
zum COUNT. Da braucht es keinen Zugriff auf die Tabelle
mehr, ORACLE liest dann nur noch den INDEX.
Daniel
Specialist
 
Beiträge: 208
Registriert: 10.09.2003, 13:20
Wohnort: Bielefeld
Dank erhalten: 15 mal

Re: Performance Problem

Beitragvon DeathAndPain » 28.09.2017, 15:37

Was hilft mir das; wir sind auf Sybase. :P
DeathAndPain
Specialist
 
Beiträge: 308
Registriert: 05.05.2006, 10:14
Dank erhalten: 79 mal
Ich bin: Entwickler/in

Re: Performance Problem

Beitragvon Daniel » 28.09.2017, 15:44

Auch Sybase wird erkennen daß ein Index-Zugriff reicht.
Bei HANA klappt das auch.
Daniel
Specialist
 
Beiträge: 208
Registriert: 10.09.2003, 13:20
Wohnort: Bielefeld
Dank erhalten: 15 mal


Zurück zu ABAP® für Anfänger

  Aktuelle Beiträge   
Barcodes in Warenbewegungen & Belegen
vor 14 Stunden von marc.braun 0 Antw.
HTML Daten als Anhang an Mail unter AOO
vor 16 Stunden von SAP_ENTWICKLER 0 Antw.
SAP Access & Identity Management - noch aktuell?
vor 19 Stunden von SaskuAc 0 Antw.
gelöst SELECT...WHERE mit ähnlichen String-Feldern
vor 18 Stunden von Suta_K 4 Antw.
gelöst Seitensteuerung Adobe Forms
vor 15 Stunden von Lucyalison 12 Antw.

  Ähnliche Beiträge beta
gelöst Performance Problem
22.11.2017, 12:20 von DeathAndPain 2 Antw.
Speicher & Performance Problem bei XML einlesen
17.06.2011, 09:13 von Zubasa 8 Antw.
SQL und Performance
24.11.2005, 09:04 von Andreas G 2 Antw.
Performance von INE vs. EEQ
22.08.2013, 10:40 von black_adept 3 Antw.
Inner Joins - Performance
09.02.2006, 13:52 von Gast 10 Antw.

 

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder

Feedback ...?

Was können wir verbessern? Hinterlasse deine Kontaktdaten, wenn du eine direkte Antwort möchtest.

... Absenden!