[NEWSboard IBMi Forum]
Seite 1 von 2 1 2 Letzte
  1. #1
    Registriert seit
    Mar 2005
    Beiträge
    74

    SQL Ersatz für SETGT/READE Kombi

    Hallo,

    ich bin auf der Suche nach einem performanten SQL Ersatz für die RPG SETGT/READPE Kombination zur Ermittlung von Sätze mit einem "gültig ab" Datum.

    Die Situation kennen sicherlich einige: Es gibt ein Tabelle mit Sätze die ein "gültg ab" Datum haben. Um für ein Datum nun den richtigen Satz zu finden, bediene ich mich der SETGT und READPE Operationen:

    Code:
    setgt (yKey:yDatum) tabelle;
    readpe (yKey) tabelle;      
    if not %eof();                             
      return yWert;                       
    endif;
    Ich suche nun eine performante Lösung dafür in SQL.

    Um das gleiche Ergebnis für die Problematik zu bekommen, fallen mir zwei Varianten ein um den Wert zu ermitteln:

    Variante 1:

    Code:
    SELECT wert                  
    FROM   Tabelle
    WHERE  key=:yKey                  
           AND gueltig_ab<=:yDatum        
    ORDER BY gueltig_ab DESC              
    FETCH FIRST ROW ONLY
    Variante 2:

    Code:
    SELECT wert                              
    FROM   tabelle                 
    WHERE  key=:yKey                            
           AND gueltig_ab=                           
              (SELECT MAX(gueltig_ab)                
               FROM   tabelle      
               WHERE  key=:yKey                  
                      AND gueltig_ab<=:yDatum        
              );

    Ich habe ein kleine Testfall aufgebaut, der die Routinen unter gleichen Bedingungen mehrere 1000x durchführt. Dabei kommen folgende Zeiten raus:

    SETGT/READPE: 1,788
    SQL Variante 1: 13,381
    SQL Variante 2: 12,445

    Die SQL-Variante mit dem Subselect ist etwas schneller als die Variante mit ORDER BY. Beide sind aber deutlich langsamer als die SETGT/READPE-Variante.

    Hat jemand noch eine Idee, wie mit SQL diese Problematik besser gelöst werden kann?

    Gruß
    Martin

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    Deine SQL's sind ja soweit OK, aber du benötigst halt einen absteigenden Index.
    Dann wird SQL auch wieder schneller.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  3. #3
    Registriert seit
    Mar 2002
    Beiträge
    5.287
    ... ein zusätzliches Feld gültig_bis (kann auch per Trigger gefüllt werden) hilft da Wunder...

    D*B
    AS400 Freeware
    http://www.bender-dv.de
    Mit embedded SQL in RPG auf Datenbanken von ADABAS bis XBASE zugreifen
    http://sourceforge.net/projects/appserver4rpg/

  4. #4
    Registriert seit
    Mar 2005
    Beiträge
    74
    @Fuerchau Ein absteigender Index hat keine Änderungen gebracht.
    @BenderD Was muss mit dem Feld gemacht werden?

  5. #5
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    Das Problem ist ja, dass ein Gültig-Ab immer für alle vergangenen Daten gilt.
    SQL baut also immer ein Resultset mit mehreren Sätzen zusammen obwohl nur einer benötigt wird.
    Mittels "Order by .. desc fetch first 1 rows only" solltest du hier einschränken.

    Die bessere Methode ist tatsächlich, ein "Gültig-Bis"-Feld einzuführen.
    D.h., hier kann es rein technisch nur 1 Satz geben wenn das Feld auch Unique-Key ist.
    Es kann ja eigentlich nicht mehrere Gültig-Bis geben die am selben Tag enden.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  6. #6
    Registriert seit
    Mar 2005
    Beiträge
    74
    Fetch first row only ist ja schon angegeben.

    Die Keys sind unique, auch bei gültig ab. Es gibt jeweils nur einen Satz mit gültig ab. Auch ist die Tabelle, mit der ich die Zeiten teste, sehr klein. Trotzdem sind die großen Zeitunterscheide.

  7. #7
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    Wobei ich mich frage, welche Zeiten du hier hast.
    Bei SETGT/REDPE fast 2 Sekunden?
    Dann hast du da ganz andere Probleme, das sollte auch eher 0,001 Sekunden dauern.
    Wenn das 2 Millisekunden sind, dann würde ich mich um die 13 Millisekunden auch nicht sorgen.
    Ggf. ist das nämlich nur der 1. Zugriff mit SQL-Analyse und Datei-Open.
    Im Wiederholungsfall (ODP bleibt) wird SQL dann auch schneller.
    Mach das mal ein paar 100 oder 1000 Mal.
    SQL hat natürlich immer einen Overhead und ist beim Einzelsatz lesen langsamer.
    Beim Einzelsatz brauch man aber auch keinen Cursor, hier kann man direkt einen "select ... into ... from ..." verwenden und spart somit die Open/Fetch/Close. Das bringt auch schon mal was.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  8. #8
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    Nachtrag:
    Prüfe mal im Debug-Modus ob dein Desc-Index überhaupt verwendet wird.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  9. #9
    Registriert seit
    Mar 2002
    Beiträge
    5.287
    Zitat Zitat von mwithake Beitrag anzeigen
    @Fuerchau Ein absteigender Index hat keine Änderungen gebracht.
    @BenderD Was muss mit dem Feld gemacht werden?
    ... dann holt man sich die Sätze mit:
    SELECT wert
    FROM Tabelle
    WHERE key=:yKey
    AND :yDatum between gilt_ab and gilt_bis
    das sollte schneller sein und macht vor allem das Leben einfacher, da sich das im View Layer abbilden lässt.
    Beim neuesten schreibt man dann in gilt_bis Highval rein.
    D*B
    AS400 Freeware
    http://www.bender-dv.de
    Mit embedded SQL in RPG auf Datenbanken von ADABAS bis XBASE zugreifen
    http://sourceforge.net/projects/appserver4rpg/

  10. #10
    Registriert seit
    Mar 2005
    Beiträge
    74
    Das muss wohl am SQL-Overhead liegen.

    @Fuerchau: Die Werte sind schon für 100.000 Aufrufe (wie in der ersten Frage angegeben). Das "Into" hatte ich zur Übersicht rausgenommen, die Aufrufe fanden mit SELECT INTO statt. Visual Explain zeigt auch an, das der absteigende Index nicht genommen wird.

    @Bender: Die Abfrage mit gültig_bis und BETWEEN dauerte (ohne Index Optimierung und View) etwas länger als die beiden anderen. Vielleicht sind die Anzahl der Sätze, die derzeit in der Tabelle vorhanden sind, auch zu gering um einen Unterschied festzustellen.

    Ich hatte die Frage einfach mal in dem Raum gestellt, da ich immer wieder auf diese Art der Abfrage stoße. Vielleicht hätte es ja einen eleganteren SQL Weg gegeben, dieses Problem zu lösen (RPG hat ja auch Operationen für diesen Art des Zugriffs).
    Besonders in SQL-Abfrage, die einen Wert aus der "Gültig_AB" Tabelle dazu holen müssen, wäre es interessant. Die Abfrage ist dann sehr kompliziert, Select mit Unterselect auf "Gültig_AB" Tabelle und darauf wieder Unterselect für die MAX() Funktion. Mehrere 1000 Sätze kommen dann schnell zustande, welche die Unterabfrage dann wieder auslösen und den Geschwindigkeitsunterschied bemerkbar machen.

    Sicherlich kann man die Funktion auch mit Stored-Procedure implementieren (mit allen möglichen Optimierung, Deterministic etc). Aber hier wäre der Optimizer wieder ein bisschen außen vor, falls es doch mal diese Art der Abfragen optimieren könnte. Und um die Abfrage in der Procedure schnell zu bekommen müssten man wieder auf RPG zurückgreifen, was wir in unsere Java-Umgebung nicht mehr so gerne möchten.

  11. #11
    Registriert seit
    Aug 2001
    Beiträge
    2.873
    Für Einzelsatz-Zugriffe ist SQL im Vergleich zu RPG um einiges langsamer, das ist bekannt. Der Faktor 1:10 erscheint mir allerdings etwas hoch.

    Nur so ein paar Fragen am Rande.
    Befinden sich die aufrufende Prozeduren und die rufenden Prozeduren im gleichen Modul?
    Befinden sich die aufgerufenen Prozeduren in einem Service Programm oder sind die Module gebunden?
    In welcher Aktivierungsgruppe werden die Caller und aufgerufenen Prozeduren ausgeführt?
    Wie wird die Option CLOSQLCSR im Umwandlungsbefehl (oder SET OPTION Statement) der (embedded) SQL Module gesetzt? *ENDMOD oder *ENDACT?

    Birgitta
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  12. #12
    Registriert seit
    Mar 2005
    Beiträge
    74
    Die Prozedur befindet sich im einem Serviceprogramm, das mit ACTGRP(*CALLER) umgewandelt wird. Der Parameter CLOSQLCSR im CRTSQLRPGI, mit das Serviceprogramm erstellt wird, steht auf *ENDACTGRP, SET OPTION wird nicht verwendet.
    Das aufrufende Programm hat die Aktivierungsgruppeneinstellung *NEW.

Similar Threads

  1. READ / READE in free-rpg
    By Gimli in forum IBM i Hauptforum
    Antworten: 6
    Letzter Beitrag: 10-03-03, 12:08
  2. Ersatz für IBM Site-Manager
    By lossin in forum IBM i Hauptforum
    Antworten: 1
    Letzter Beitrag: 13-09-02, 13:28
  3. Wegfall Office/400 - Ersatz?
    By STJ in forum IBM i Hauptforum
    Antworten: 1
    Letzter Beitrag: 27-04-01, 09:49

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • You may not post attachments
  • You may not edit your posts
  •