Performance Problem

Die Frage ist als "gelöst" markiert. Den entsprechend Beitrag findest du hier.

Getting started ... Alles für einen gelungenen Start.
15 Beiträge • Seite 1 von 1
15 Beiträge Seite 1 von 1

Performance Problem

Beitrag von ChrissixD (ForumUser / 27 / 17 / 0 ) »
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ß

gesponsert
Stellenangebote auf ABAPforum.com schalten
kostenfrei für Ausbildungsberufe und Werksstudenten


Re: Performance Problem

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
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.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
ChrissixD


Re: Performance Problem

Beitrag von ChrissixD (ForumUser / 27 / 17 / 0 ) »
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ß

Re: Performance Problem

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
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.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
ChrissixD


Re: Performance Problem

Beitrag von black_adept (Top Expert / 3943 / 105 / 886 ) »
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

Re: Performance Problem

Beitrag von ChrissixD (ForumUser / 27 / 17 / 0 ) »
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?

Re: Performance Problem

Beitrag von ChrissixD (ForumUser / 27 / 17 / 0 ) »
@black_adept Wie meinst du das mit Kommentaren?

Re: Performance Problem

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
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.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
ChrissixD


Re: Performance Problem

Beitrag von Daniel (Specialist / 314 / 68 / 44 ) »
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.

Re: Performance Problem

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
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.

Re: Performance Problem

Beitrag von Daniel (Specialist / 314 / 68 / 44 ) »
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.

Re: Performance Problem

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
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.

Re: Performance Problem

Beitrag von Daniel (Specialist / 314 / 68 / 44 ) »
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.

Re: Performance Problem

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
Was hilft mir das; wir sind auf Sybase. :P

Re: Performance Problem

Beitrag von Daniel (Specialist / 314 / 68 / 44 ) »
Auch Sybase wird erkennen daß ein Index-Zugriff reicht.
Bei HANA klappt das auch.

Seite 1 von 1

Vergleichbare Themen

2
Antw.
1028
Views
Performance Problem
von ChrissixD » 21.11.2017 07:49 • Verfasst in ABAP® für Anfänger
70
Antw.
16057
Views
Performance-Problem
von cuncon » 27.02.2018 07:41 • Verfasst in ABAP® für Anfänger
18
Antw.
6515
Views
Performance-Problem bei SELECT
von Charadin » 22.10.2007 08:10 • Verfasst in ABAP® Core
8
Antw.
4214
Views
Speicher & Performance Problem bei XML einlesen
von Zubasa » 15.06.2011 13:48 • Verfasst in ABAP® für Anfänger
1
Antw.
151
Views
Laden Archivierter Daten - Performance Problem
von tom125 » 03.02.2021 10:44 • Verfasst in ABAP® für Anfänger

Über diesen Beitrag


Die Frage ist als "gelöst" markiert. Den entsprechend Beitrag findest du hier.

Unterstütze die Community und teile den Beitrag für mehr Leser und Austausch

Aktuelle Forenbeiträge

Zwischensumme Adobe Forms
vor 3 Tagen von Lucyalison 1 / 64
Interne Tabelle
vor 5 Tagen von black_adept 2 / 133
MaLo-Checker in ABAP
vor einer Woche von A6272 6 / 254

Newsletter Anmeldung

Keine Beiträge verpassen! Wöchentlich versenden wir lesenwerte Beiträge aus unserer Community.
Die letzte Ausgabe findest du hier.
Details zum Versandverfahren und zu Ihren Widerrufsmöglichkeiten findest du in unserer Datenschutzerklärung.

Aktuelle Forenbeiträge

Zwischensumme Adobe Forms
vor 3 Tagen von Lucyalison 1 / 64
Interne Tabelle
vor 5 Tagen von black_adept 2 / 133
MaLo-Checker in ABAP
vor einer Woche von A6272 6 / 254

Unbeantwortete Forenbeiträge

Zwischensumme Adobe Forms
vor 3 Tagen von Lucyalison 1 / 64
Group Items auf einer Filterbar
vor einer Woche von Bright4.5 1 / 107
tRFC Transaktionen SM58
vor 4 Wochen von A6272 1 / 140