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

    Angry JDBC SQL Performabce

    Hallo Forum,

    nachdem ich hier schon im Forum nach dem Problem gesucht habe und immer noch nicht fündig geworden bin, hier meine Bitte um Hilfe. Das Problem ist die performance beim schreibenden JDBC Zugriff. Ich erstelle mir eine Tabelle mit

    CREATE TABLE SQLTEST (FLD1 CHAR (10 ) NOT NULL WITH
    DEFAULT, FLD2 CHAR (10 ) NOT NULL WITH DEFAULT)

    Wenn ich jetzt mit SQL COBOL 10.000 Sätze in die Tabelle einfüge, dauert das ca. 1s. Auszug :

    PERFORM WITH TEST AFTER UNTIL V-ZAEHLER > 10000
    EXEC SQL
    INSERT INTO SQLTEST
    VALUES ("FLDA", "FLDB")
    END-EXEC
    ADD 1 TO V-ZAEHLER
    END-PERFORM.

    Mache ich dasselbe mit einem JAVA-programm, dauert das ganze 19s. Ohne Verwendung von ProparedStatements noch länger. Der Sourcecode sieht so aus :

    int j = 0;
    try {
    PreparedStatement ps = AS400.prepareStatement("INSERT INTO sqltest VALUES(?, ?)");

    for (int i = 0;i<10000;i++) {
    ps.setString(1, "FLDA");
    ps.setString(2, "FLDB");
    ps.addBatch();
    j++;
    if (j==1000) {
    ps.executeBatch();
    j=0;
    }
    }
    } catch (Exception ex) {
    ex.printStackTrace();

    }

    Was läuft hier verkehrt ? Habe das Gefühl das bei jedem executBatch schon auf die Tabelle der iSeries zugegriffen und ein ODP erstellt wird. Allerdings ist die Maschine während des ganzen Vorganges nicht ausgelastet. CPU <10%, kein Paging, nichts. Version 5.2 ist im Einsatz auf einer 810. Das Problem triff aber genau so auf einer 870 mit 5.3 und einer 170 mit 5.2 auf.
    Bin ratlos und für jeden Tip dankbar.

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    20.695
    Durch die Batch-Variante wird eben 1000 Mal ein Insert-Befehl aufgerufen.
    Warum verwendest du nicht direkt Execute() ???
    Durch den Batch wird das ganze erst mal gesammelt und dann als Stapel übertragen. Ich habe keine Ahnung ob Prepared dann überhaupt funktioniert.
    Im COBOL verwendest du ja auch kein Batch (was es da ja auch nicht gibt).
    Allerdings darf Java schon mal 3-5 Mal langsamer sein.
    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
    Jul 2005
    Beiträge
    232
    Zitat Zitat von Fuerchau
    Durch die Batch-Variante wird eben 1000 Mal ein Insert-Befehl aufgerufen.
    Warum verwendest du nicht direkt Execute() ???
    Durch den Batch wird das ganze erst mal gesammelt und dann als Stapel übertragen. Ich habe keine Ahnung ob Prepared dann überhaupt funktioniert.
    Im COBOL verwendest du ja auch kein Batch (was es da ja auch nicht gibt).
    Allerdings darf Java schon mal 3-5 Mal langsamer sein.
    Der reine Execute dauert 24s, ohne PreparedStatement 28s. Das aber auch nur, weil der Feldinhalt gleich ist. Verwende ich, wie normalerweise der Fall, unterschiedliche Werte, dann dauert das nochmals länger, da meines Wissens nach die AS400 dann immer einen neuen ODP baut. Habe seit langem schon die Erfahrung gemacht, das diese Methode (ExecuteBatch) die bessere ist. Wird auch oft in der Literarur darauf verwiesen. Nur darf die Anzahl der Statements, welche im Batch ausgeführt werden, nicht zu große sein, da der Speicher sonst überläuft (ich glaube es kommt ein Heap-Überlauf)
    3..5 mal langsamer wäre ja noch ok, aber ich muss demnächst Nachts des öfteren mehrere 100.000 Sätze übertragen. Komischerweise ist selbst eine 870 hier kaum schneller als die 810. Ein Performanceproblem kann es also nicht sein.

  4. #4
    Registriert seit
    Jul 2005
    Beiträge
    232
    Habe es eben auch nochmals über Stored Procedures versucht. Ergebnis ist das gleiche. Es scheint also nicht von der Art der Statements abzuhängen, sondern von der Anzahl.

  5. #5
    Registriert seit
    Jul 2005
    Beiträge
    1.053
    Zitat Zitat von pwrdwnsys
    Habe es eben auch nochmals über Stored Procedures versucht. Ergebnis ist das gleiche. Es scheint also nicht von der Art der Statements abzuhängen, sondern von der Anzahl.
    Kann man das vielleicht über ein RGP Programm mit embebbed SQL erledigen ?

    In ein RGP kann man schließlich Cobol und SQL als prozeduren aufrufen .

    Mit freundlichen Grüßen as400.lehrling

  6. #6
    Registriert seit
    Feb 2001
    Beiträge
    20.695
    Ich kenne mich jetzt nicht so gut in Java aus. Vielleicht liegt es daran, dass der Typ der Parameter nicht stimmt. Ggf. kannst du die Parameter selber definieren.
    Wie sieht denn die Verbindungsfolge aus ?
    Vielleicht ist ja Transaktionssteuerung eingeschaltet und die Tabelle wird nicht aufgezeichnet ?
    Da Java auf der AS/400 wohl schlecht zu debuggen ist, kannst du ja mal zwischen den Inserts (also nicht per Batch) mal einen Delay von 1s einbauen und dann per "WRKOBJLCK SQLTEST *FILE" den Zugriffsjob rausfinden und ins Joblog schauen.
    Vielleicht kannst du ja auch per Execute("call qcmdexc parm('STRDBG UPDPROD(*YES)', 0000000020.00000)" den Job in DEBUG-Modus versetzen um dann die Joblog-Hinweise zu analysieren.

    Es schein wohl so, dass Prepared irgendwie nicht funktioniert oder implizit CommitTrans (o.ä.) ausgeführt wird.
    Eigentlich dürften so extreme Unterschiede nicht vorkommen.
    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

  7. #7
    Registriert seit
    Jul 2005
    Beiträge
    232
    Danke @Fuerchau,den Debugger hab ich schon eingeschaltet (über QAQQINI MESSAGES_DEBUG *YES) Der zeigt mir nur die Ausführung der Batch-Blöcke an. (Alle 1000 Anweisungen) Das Problem liegt aber wohl nicht nur im JAVA, denn wenn viele Anweisungen über den Operations-Navigator gemacht werden, ist die Performance auch verdammt schlecht. Ich vermute, das der Navigator auch in JAVA geschrieben ist und sich deshalb analog verhält. Das Problem ist, wenn ich mit demselben Programm und auch JDBC auf eine DB/2 Datenbank unter Linux zugreife, kann ich gar nicht so schnell die Stoppuhr drücken, wie das Programm durch ist. Vielleicht ist auch das Netwerk der Flaschenhals. Es kommt zwar ein 100MBit Adapter zum EInsatz, sowohl auf der iSeries als auch auf dem PC. Habe mich mal "extern" via ISDN mit der iSeries verbunden. Das Programm läuft ewig. Anscheinend laufen sehr viele Informationen zwischen der iSeries und dem Client je Statement. Ich war bisher der Meinung, das die Statements auf der iSeries gesammelt werden, bevor diese beim executeBacht übertragen werden. Dafür spricht ja auch der Speicherüberlauf auf dem PC. Das wäre bisher die plausibelste Erklärung. Das scheint aber so nicht richtig zu sein.

    Im Notfall muss ich mal die Leitung tracen um den Traffic / Inhalt zu messen.

  8. #8
    Registriert seit
    Feb 2001
    Beiträge
    20.695
    DAS ist eben der Unterschied !
    Normalerweise dürfte NUR DIE 1. Anweisung zu sehen sein (das ist so, wenn ich z.B. vom PC per ODBC mit VB/VBA zugreife).
    Es sieht also so aus, dass Java den SQL eben immer neu zusammenbaut und daher Prepared AUF DER AS/400 nicht läuft. Scheinbar gilt der Prepared nur intern für Java.

    Suche da mal nach Möglichkeiten !
    Kannst du ggf. einstellen, dass ein SQLPKG (SQL-Paket) verwendet werden soll ?

    PS:
    ExecuteBatch ist eine reine Java/DAO/ADO-Funktion und hat mit SQL rein gar nichts zu tun.
    Der Speicherüberlauf passiert ja auf dem PC und nicht auf der AS !
    Das Sammeln der SQL's wird rein durch die SQL-Runtime durchgeführt.
    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
    Sep 2002
    Beiträge
    47
    Hi!

    Hab Dein Beispiel mal etwas angepasst und bei uns laufen lassen.
    Bei uns dauert das zw. 3-5 Sekunden.

    Ich habs hier getestet mit JTOpen 4.8 und V5R3 auf ner
    520. Sicher das alle PTF's unter OS/400 installiert sind und die akt. JDBC Treiber benutzt werden?


    Zeiten:

    Starte: Mon Sep 05 19:20:15 CEST 2005
    JDBC init: Mon Sep 05 19:20:16 CEST 2005
    Create Table: Mon Sep 05 19:20:16 CEST 2005
    Insert 10.000: Mon Sep 05 19:20:19 CEST 2005
    Close: Mon Sep 05 19:20:19 CEST 2005


    Dein Beispiel:

    import java.io.PrintWriter;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.Statement;
    import java.util.Date;

    /**
    * @author xxx
    *
    */
    public class Test {

    /**
    *
    */
    public Test() {
    super();
    // TODO Auto-generated constructor stub
    }

    /**
    * @param args
    */
    public static void main(String args) {

    long start = System.currentTimeMillis();

    try{
    DriverManager.setLogWriter( new PrintWriter(System.out) );
    Class.forName( "com.ibm.as400.access.AS400JDBCDriver" );
    Connection con = DriverManager.getConnection("jdbc:as400://xxx.xxx.xxx.xxx/qsys.lib/xxxx.lib/","xx", "xx");
    Statement stmt = con.createStatement();

    long init = System.currentTimeMillis();


    try{
    stmt.execute(" CREATE TABLE xxxx.SQLTEST (FLD1 CHAR (10 ) NOT NULL WITH DEFAULT, FLD2 CHAR (10 ) NOT NULL WITH DEFAULT) ");
    }catch(Exception e){
    System.err.println("Fehler: "+e.getMessage());
    }

    long create = System.currentTimeMillis();

    PreparedStatement ps = con.prepareStatement("INSERT INTO nslib.sqltest VALUES(?, ?)");
    for (int i = 0; i<10000;i++) {
    ps.setString(1, "FLDA");
    ps.setString(2, "FLDB");
    ps.addBatch();
    }
    ps.setString(1, "FLDA");
    ps.setString(2, "FLDB");
    ps.executeBatch();

    long insert = System.currentTimeMillis();

    stmt.close();
    con.close();

    long close = System.currentTimeMillis();

    System.out.println("Starte: " + new Date(start));
    System.out.println("JDBC init: " + new Date(init));
    System.out.println("Create Table: " + new Date(create));
    System.out.println("Insert 10.000: " + new Date(insert));
    System.out.println("Close: " + new Date(close));

    }
    catch(Exception e){
    e.printStackTrace();
    System.err.println("Fehler: " + e.getMessage());
    System.exit(1);
    }

    System.exit(0);
    }

    }
    Ciao
    Nili

  10. #10
    Registriert seit
    Feb 2001
    Beiträge
    20.695
    Sag ich doch, Java ca. 3-5 Mal länger !
    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

  11. #11
    Registriert seit
    Jul 2005
    Beiträge
    232
    PTF's sind alle drin (V5R2) Ich vermute mal das es am Treiber liegt. Werds morgen gleich mal testen. Habe bisher immer nur die "mitgelieferten" jt400 Treiber aus dem IFS benutzt. Kann nur so sein. Hoffe ich.

  12. #12
    Registriert seit
    Jul 2005
    Beiträge
    232
    @Nili,

    ist Deine Programm direkt auf der /400 gelaufen oder auf einem externen PC ? Und mit welcher .jar-Datei ? jt400 oder jt400native ?

    THX

Similar Threads

  1. RPGLE - SQL
    By christian_lettner in forum NEWSboard Programmierung
    Antworten: 2
    Letzter Beitrag: 16-11-06, 10:15
  2. SQL - Cursor vernichten ?!?
    By FNeurieser in forum NEWSboard Programmierung
    Antworten: 3
    Letzter Beitrag: 11-10-06, 14:53
  3. SQL und OBJLCK
    By malzusrex in forum IBM i Hauptforum
    Antworten: 8
    Letzter Beitrag: 19-09-06, 11:04
  4. SQL - Fehler
    By Kaufmann in forum IBM i Hauptforum
    Antworten: 11
    Letzter Beitrag: 28-06-06, 14:11
  5. SQL .. for update of (RPG embedded SQL)
    By loeweadolf in forum NEWSboard Programmierung
    Antworten: 2
    Letzter Beitrag: 01-06-06, 09:43

Berechtigungen

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