schnelle suche

Alles rund um die Sprache ABAP®: Funktionsbausteine, Listen, ALV
10 Beiträge • Seite 1 von 1
10 Beiträge Seite 1 von 1

schnelle suche

Beitrag von dimes (Specialist / 146 / 0 / 0 ) »
Hallo Leute,

Hab da mal ne frage.
Ich muss über die mseg selektieren, und da wir da sehr viele Einträge haben dauert das ziemlich lang...

Nun Frage ich mich wie die ein paar secunden sparen kann:

selection:

Code: Alles auswählen.

  select      lgort umlgo matnr meins menge mblnr mjahr werks umwrk
              bwart
    into     (itab1-vo_ort, itab1-na_ort, itab1-matnr, itab1-meins,
              itab1-menge,  itab1-mblnr,  itab1-mjahr, itab1-out_werk,
              itab1-in_werk, tmp_bwart)
    from      mseg
    where     mjahr    in mjahr_tab
          and parent_id = space       "übergeordneten Zeile
          and kzbew     = ' '         "Bewegungskennzeichen
          and lgort    <> space       " von Lagerort
          and umlgo    <> space       "nach Lagerort
          and bwart    in (200, 300, 302)
          and werks    in s_vowerk
          and umwrk    in s_nawerk
          and matnr    in s_matnr
          and mblnr    in s_mblnr
          and lgort    in s_vo_ort
          and umlgo    in s_na_ort.

*   Datum
    select single budat into (tmp_budat) from mkpf
                                       where mblnr = itab1-mblnr
                                         and mjahr = itab1-mjahr
                                         and budat in s_datum.
    if sy-subrc = 0.
      concatenate tmp_budat+4(2) tmp_budat(4)
                  into itab1-monat separated by '.'.
    else.
      continue.
    endif.

*   Materialgruppe
    if s_kondm is initial.
      select single kondm into (itab1-kondm)
                          from mvke
                         where matnr  = itab1-matnr
                           and vkorg  = '0003'
                           and vtweg  = '31'.
    else.
      select single kondm into (itab1-kondm)
                      from mvke
                     where matnr  = itab1-matnr
                       and kondm in s_kondm
                       and vkorg  = '0003'
                       and vtweg  = '31'.
      if sy-subrc <> 0.
        continue.
      endif.
    endif.
    collect itab1.
  endselect.



Ist das eigendlich egal wie ich z.B. die Where-Bedingungen anordne oder sollte ich lieber die vergleiche mit den range-tabellen höher stellen, oder ist das egal. Hat jemand von euch viilleicht noch nen schönen Performance-Tip für mich.

Gruss
dimes

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


Beitrag von PsychoMantis (ForumUser / 98 / 0 / 0 ) »
Hallo dimes,
zuerst einmal sollte man immer select...endselect-Schleifen vermeiden und stattdessen mit dem Zusatz "into table" arbeiten. Also z.B.:

Code: Alles auswählen.

select ... from mseg into table gt_mseg where ...
Dann kannst du noch versuchen die anderen Datenbankabfragen mittels join-Anweisung (F1-Hilfe gibt Beispiele) in den ersten Select zu integrieren. Allein die erste Maßnahme sollte dein Programm schon extrem beschleunigen.

Gruß
Psy

Beitrag von joachim (ForumUser / 70 / 0 / 2 ) »
hallo dimes,
wie psy würde ich auch alles in eine itab lesen. fuer mkpf/mseg habe ich mir eine schöne view aufgebaut,
innerhalb der view hast du ja auch die möglichkeit selektionsbedingungen
zu benutzen, was deine view auch schlank machen könnte.
joachim

Beitrag von dimes (Specialist / 146 / 0 / 0 ) »
Danke für die Tip´s

Hab noch nicht´s mit view´s gemacht, also las ich das erstmal und guck mir das später mal an, wie das gehen soll... :(

HAb das jetzt so gemacht wie PsychoMantis mir vorgeschlagen hat:

Code: Alles auswählen.


  data: tmp_mseg  type table of mseg,
        tmp_budat type mkpf-budat,
        tmp_monat type char7.

field-symbols <tmp_mseg> like line of tmp_mseg.

  select *
    into table tmp_mseg
    from  mseg
    where     mjahr    in mjahr_tab
          and parent_id = space       "übergeordneten Zeile
          and lgort    <> space       "von  Lagerort
          and bwart    in (301, 303, 305, 311, 313, 315, 101)
          and matnr    in s_matnr
          and mblnr    in s_mblnr.


loop at tmp_mseg assigning <tmp_mseg>.
*BEDINGUNGEN
*   Datum
    select single budat into (tmp_budat) from mkpf
                                        where mblnr = <tmp_mseg>-mblnr
                                          and mjahr = <tmp_mseg>-mjahr
                                          and budat in s_datum.
    if sy-subrc <> 0. continue. endif.

*   Bewegungsart
*   Es wird geschaut um welche Bewegungsart es sich handelt, da
*   der sich die von/nach-Lagerorte (Werk auch) abweichen.
*   z.B '101' nachlagerort = lgort
*       '311' nachlagerort = umwrk
    if <tmp_mseg>-bwart = '101'.
      check <tmp_mseg>-werks in s_nawerk
        and <tmp_mseg>-lgort in s_na_ort.
    else.
      check <tmp_mseg>-werks in s_vowerk
        and <tmp_mseg>-umwrk in s_nawerk
        and <tmp_mseg>-lgort in s_vo_ort
        and <tmp_mseg>-umlgo in s_na_ort.
    endif.

*   Materialgruppe
    if not s_kondm is initial.
      select single kondm into (itab1-kondm)
                      from mvke
                     where matnr  = <tmp_mseg>-matnr
                       and kondm in s_kondm
                       and vkorg  = '0003'
                       and vtweg  = '31'.
      if sy-subrc <> 0. continue. endif.
    else.
*BEFUELLUNG
      select single kondm into (itab1-kondm)
                          from mvke
                         where matnr  = <tmp_mseg>-matnr
                           and vkorg  = '0003'
                           and vtweg  = '31'.
    endif.


    concatenate tmp_budat+4(2) tmp_budat(4) into tmp_monat
                                            separated by '.'.

    itab1-monat       = tmp_monat.
    itab1-mblnr       = <tmp_mseg>-mblnr.
    itab1-matnr       = <tmp_mseg>-matnr.
    itab1-meins       = <tmp_mseg>-meins.
    itab1-menge       = <tmp_mseg>-menge.

*   Von/Nach -Werk & -Ort
    if mseg-bwart = '101'.
      itab1-out_werk = '0'.
      itab1-in_werk  =  <tmp_mseg>-werks.
      itab1-vo_ort   = '0'.
      itab1-na_ort   =  <tmp_mseg>-lgort.
    else.
      itab1-out_werk =  <tmp_mseg>-werks.
      itab1-in_werk  =  <tmp_mseg>-umwrk.
      itab1-vo_ort   =  <tmp_mseg>-lgort.
      itab1-na_ort   =  <tmp_mseg>-umlgo.
    endif.

    collect itab1.
endloop.

endform.                    " get_data
Hab ihr vieleicht noch paar Tip´s?

Danke & Gruss
dimes

Beitrag von DeathGuardian (Expert / 759 / 0 / 3 ) »
Noch ein bisschen schneller geht es, wenn du aus den 2 Selects Einenen machst.
MKPF und MSEG kannst du miteinander Joinen.

Beitrag von Olaf P. (ForumUser / 61 / 0 / 0 ) »
Hi,
ich würde die Tabelle MKPF und MSEG mit einem Join (Hilfe zu INNER JOIN) lesen, damit wird der explizite SELECT SINGLE nicht mehr benötigt.

Prinzipiell ist gegen eine SELECT-Schleife nichts einzuwenden, vor allem, wenn man mit sehr grossen Datenmengen arbeitet und diese durch Programmlogik aggregiert. In diesem Fall gerät man nicht in Speicherprobleme und die Performance kann aufgrund des geringeren Speicherbedarfs erheblich besser sein.

Was man aber nicht machen sollte sind geschachtelte SELECT-Schleifen, da diese enorme DB-Requests erzeugen. In diesen Fällen kommen Joins oder FOR ALL ENTRIES zum Tragen.

Es bietet sich zum Teil an im Testsystem ein lokales Programm (sofern erlaubt => Systemänderbarkeit) anzulegen und die Performance des Zugriffs zu testen, da häufiger mehrere Wege zum gewünschten Ergebnis führen und man nicht immer mit absoluter Sicherheit sagen kann, welches der Beste ist.

Warum ist die explizite Feldauswahl im letzten Coding dem * gewichen? Damit wird massenhaft Speicher auf der DB und dem Appl-Server verbraten, weniger Sätze passen in einen Kontrollblock, die Netzwerklast steigt, .....

Noch ein Tipp zum Schluss:
Ich würde wenn möglich keine Hard-Codings verwenden, da sich die Welt irgendwann ändern kann und dann geht die Suche los.

Ich finde es besser, wenn diese auf dem Selektionsbild sichtbar sind. Dort kann man sie auch bei Bedarf auf nicht-eingabebereit schalten.

Viele Grüße

Olaf

Beitrag von Gast ( / / 0 / 3 ) »
servus olaf,
Ist das eigendlich egal wie ich z.B. die Where-Bedingungen anordne
...
...nein, ist es nicht.

alle primärschlüssel der tabelle müssen a) an der richtigen stelle (als erstes in der where-bedingung), b) in der richtigen reihenfolge und c) (wenn möglich) ohne unterbrechung angegeben werden, damit mittels binärer strategie gesucht werden kann.

a) sollte kein problem sein. primärschlüssel zu einer tabelle findest du z.b. über die se11.

b) sollte auch kein problem sein. die reihenfolge ist deshalb wichtig, da die tabelle entprechend der reihenfolge der primärschlüssel im sortierten zustand gehalten wird. daher ist es möglich eine binäre suche anzuwenden, aber nur wenn die primärschlüssel auch an der richtigen stelle und in der richtigen reihenfolge in der where-bedingung angegeben werden.

c) oftmals kann man nicht alle primärschlüssel mit werten füllen. dazu muss man wissen, dass ab der ersten unterbrechung in der primärschlüssel-kette nur noch sequentiell weitergesucht werden kann.

d.h. bei einer tabelle mit 3 primärschlüsseln, wäre der effizienteste zugriff mittels ... where pkey1 = value1 and pkey2 = value2 and pkey3 = value3 and ... other key = other value ...

solltest du pkey3 nicht mit einem wert versorgen können, wirst du geringe einbußen haben. binäre suche mittels pkey1 und pkey2, ab dann sequentiell weiter...

wenn du z.b. nur pkey1 und pkey3 füllen kannst, aber pkey2 weglassen musst, dann wird nur über pkey1 binär gesucht und ab da nur noch sequentiell -> siehe oben: erste unterbrechung der primärschlüssel-kette => binäre suche vorbei!

zu deinen selects:

dein 2. select über die mkpf, sowie dein 3. und 4. select über die mvke sind ok.

dein 1. select holt die datensätze mittels sequentieller suchstrategie, da der erste primärschlüssel der mseg (mblnr) nicht als primärschlüssel in der select-anweisung genutzt wird.
dadurch wird der zweite primärschlüssel mjahr auch nicht mehr als primärschlüssel benutzt und ist somit wirkungslos. ändere die where-bedingung, wie folgt:

Code: Alles auswählen.

...
from mseg
where
  mblnr in s_mblnr and
  mjahr in s_mjahr_tab and
* zeile = '3. primärschlüssel der mseg'
* weglassen, da wir diesen nicht mit einem wert versorgen können
* ab hier wird sequentiell weitergesucht,
* um mittels der weiteren suchkriterien die datensätze zu ermitteln...
...
ändere dies in deinem programm, dann wird es erheblich schneller werden.

gruß
dirk

Beitrag von ereglam (Top Expert / 1829 / 2 / 7 ) »
Hallo Dirk, Olaf,

ich glaube mich daran erinnern zu können, dass die Datenbank-Optimizer heutzutage die Reiehnfolge der Primärschlüssel automatisch in die richtige Reihenfolge bringen können.
Daher würde dann die Reihenfolge im Coding egal sein. Das sollte man aber mal überprüfen, wobei möglicherweise auch nicht alle Datenbanken (gleich gut) mitspielen.
Aus dokumentativen Gründen sollte man aber ohnehin die Reihenfolge der Schlüsselfelder einhalten, wenn dies möglich ist.

Ansonsten stimme ich Dir bzgl. dem Auslassen von Primärschlüsseln zu, wenn es keinen geeigneten Sekundärindex gibt.
Gruß
Ereglam


May the Force be with your code
|| .| |.|| | .... . ..|. ||| .|. |.|. . |... . .|| .. | .... |.|| ||| ..| .|. |.|. ||| |.. .

Beitrag von Gast ( / / 0 / 3 ) »
moin,
ich glaube mich daran erinnern zu können, dass die Datenbank-Optimizer heutzutage die Reiehnfolge der Primärschlüssel automatisch in die richtige Reihenfolge bringen können.
...sollte so sein. da habe ich aber schon andere erfahrungen mit gemacht, wo es nicht so war.

...wo wir nun schon grade beim thema sind. was ich auch schon öfters hatte:

(auf die schnelle habe ich folgendes beispiel gefunden)

Code: Alles auswählen.

        SELECT
        vrsio AS vrsi5 spmon AS spmo5 vkorg AS vkor5 pkunag netwr
        FROM s777
        INTO CORRESPONDING FIELDS OF TABLE is777
        FOR ALL ENTRIES IN iknvv_kunnr
        WHERE ssour = ''
          AND vrsio = 'A00'
          AND spmon in so_spmon
          AND sptag = 0
          AND spwoc = 0
          AND spbup = 0
          AND vkorg in so_vkorg
          AND pkunag = iknvv_kunnr-kunnr.
alle primärschlüssel werden mit werten versorgt. Es sieht eigentlich ganz gut aus. wie ist es mit der laufzeit? klar, die sxxx-tabellen können schon böse groß sein, es darf also auch länger laufen... wenn ich aber obiges wie folgt ändere - zugegeben sieht zwar aus wie arsch und friedrich -, dann geht das teil ab wie die luzi :)

Code: Alles auswählen.

LOOP AT iso_tvko INTO xso_tvko.
    LOOP AT iso_datap INTO xso_datap.
      SELECT
        vrsio AS vrsi5 spmon AS spmo5 vkorg AS vkor5 pkunag netwr
        FROM s777
        APPENDING CORRESPONDING FIELDS OF TABLE is777
        FOR ALL ENTRIES IN iknvv_kunnr
        WHERE ssour = ''
          AND vrsio = 'A00'
          AND spmon = xso_datap-datap
          AND sptag = 0
          AND spwoc = 0
          AND spbup = 0
          AND vkorg = xso_tvko-vkorg
          AND pkunag = iknvv_kunnr-kunnr.
    ENDLOOP.
  ENDLOOP.
es wurde nichts anderes gemacht, als für die selektionsoptionen so_datap und so_vkorg entsprechende 1-spaltige tabellen anzulegen, um aus möglichen intervallen in den selektionsoptionen parameter bilden zu können.
(vorher müssen natürlich die parameter-tabellen mit werten gefüllt werden z.b. prügelt man so_vkorg über die tvko, um die interne tabelle iso_tvko mit parametern für unseren select zu füllen...)

durch diese vorgehensweise werden für alle primärschlüssel nur noch parameter verwendet (der in-operator wird ersetzt). dadurch wird der db-optimierer gezwungen nicht mehr mit intervallen zu arbeiten (wie es bei selektionsoptionen, je nach eingabe sein kann), sondern halt mit parametern.

auch hier könnte man sich auf den db-optimierer verlassen und annehmen, dieser würde selektionsoptionen schon irgendwie in die für ihn schnellste variante ummodellieren und verwenden. aber auch hier habe ich schon desöfteren festgestellt, dass sobald intervalle ins spiel kommen brutale performanz-verluste entstehen können...

auch wenn das beispiel total verrückt aussieht (einmaliger db-zugriff gegen geschachteltem loop + innerem mehrmaligem db-zugriff), schaue ich mir bei laufzeitproblemen immer vorkommende in-operatoren in primärschlüsseln genauer an...

gruß
dirk

Beitrag von gast ( / / 0 / 3 ) »
servus olaf,

Zitat:
Ist das eigendlich egal wie ich z.B. die Where-Bedingungen anordne
...


...nein, ist es nicht.
ups, ich meinte eigentlich dimes :) und tschüss.

Seite 1 von 1

Vergleichbare Themen

3
Antw.
736
Views
Schnelle Suche von Material im Verkaufsbeleg anpassen
von LD57 » 11.05.2021 14:48 • Verfasst in ABAP® für Anfänger
2
Antw.
1849
Views
BAPI oder FUBA was schnelle ist?
von autohandel7 » 10.08.2018 14:17 • Verfasst in ABAP® für Anfänger
5
Antw.
3054
Views
Langtext suche
von F12_man » 07.01.2008 09:41 • Verfasst in ABAP® Core
4
Antw.
2703
Views
Suche im selektionsbild
von managero » 30.06.2008 09:40 • Verfasst in Dialogprogrammierung
1
Antw.
933
Views
Suche Unterstützung
von sapfuns » 25.01.2006 11:38 • Verfasst in ABAP® Core

Aktuelle Forenbeiträge

PDF-Anzeige unter EDGE
vor 4 Tagen von jocoder 2 / 69
Etikettendruck mit SmartForms
vor einer Woche von a-dead-trousers 2 / 71

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

PDF-Anzeige unter EDGE
vor 4 Tagen von jocoder 2 / 69
Etikettendruck mit SmartForms
vor einer Woche von a-dead-trousers 2 / 71

Unbeantwortete Forenbeiträge

Zwischensumme Adobe Forms
vor 3 Wochen von Lucyalison 1 / 129
Group Items auf einer Filterbar
vor 4 Wochen von Bright4.5 1 / 165