Lotus Notes / Domino Sonstiges > Java und .NET mit Notes/Domino

Abfrage auf Oracle-DB dauert sehr labge

(1/4) > >>

DAU-in:
Ich habe mich an einem Java-Agenten versucht, der Abfragen auf eine Oracle -DB startet.

Jetzt habe ich mehrere Fragen:
a) habe ich alles recyceld, was ich recyclen muss?
b) die einzelnen Abfragen dauern zwischen 7 und 8 Sekunden, kann ich die Abfrage in checkyyyenInfo anders fassen, so dass das schneller geht?



import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.*;
import java.lang.*;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Vector;
 
import lotus.domino.*;     


public class yyyenstellenPruefung extends AgentBase {
   Session session = null;
   Database dbCurrent = null; //aktuelle DB

//für Oracle-Verbindung
   View oracleConfigView = null;
   Document docOracleConfig = null; //Konfigurationseinstellungen für Oracle   
   String strOracleServer = null; //
   String strOracleView = null; //
   String strOracleUser = null; //
   String strOraclePwd = null; //
   Connection conn=null; //
   ResultSet rs=null; //
   Statement stmt=null; //

// zu bearbeitende Dokumente

   View terminalView = null;  //zur 'Ermittlung der Dokumente
   long newDocs = 0;   
   Document terminalDoc = null; //aktuelles Terminaldoc
   Document nextDoc = null;
   
// Protokolldokument
   Document logDoc = null; //Protokoll
   GregorianCalendar cal=null; //
   Item logItem=null; //
   int logCount=0; //
   int logDocCount=1; //

   public void NotesMain() {

      try {
         System.out.println("Agent: Check für yyyenstellenaenderungen gestartet");
         session = getSession();
         AgentContext agentContext = session.getAgentContext();
         dbCurrent = agentContext.getCurrentDatabase();               // aktuelle Datenbank holen
                  
//Erstellung Protokolldokument
         cal = new GregorianCalendar();
               logDoc = dbCurrent.createDocument();
         logDoc.replaceItemValue("Form","Log");
         logDoc.replaceItemValue("Lauf","Lauf vom: " + cal.get(Calendar.DATE)+"."+(cal.get(Calendar.MONTH)+1)+"."+cal.get(Calendar.YEAR)+" " + cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+" Uhr");
         logDoc.replaceItemValue("Start",cal.get(Calendar.DATE)+"."+(cal.get(Calendar.MONTH)+1)+"."+cal.get(Calendar.YEAR)+" " + cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+" Uhr");
         
         logDoc.replaceItemValue("Log","");
         logItem = logDoc.getFirstItem("Log");      
         logEvent("Agent: Check für yyyenstellenüberprüfung gestartet");   
         logDoc.save(true,false);   //einmal abspeichern, damit Abbruch ersichtlich wird
         
         //Einlesen der Oraclekonfigurationseinstellung
         oracleConfigView    = dbCurrent.getView("(luConfig)");
         docOracleConfig       = oracleConfigView.getDocumentByKey("OracleConfig");
         strOracleServer       = docOracleConfig.getItemValueString("OracleServer");
         strOracleView          = docOracleConfig.getItemValueString("OracleView");
         strOracleUser          = docOracleConfig.getItemValueString("OracleUser");
         strOraclePwd          = docOracleConfig.getItemValueString("OraclePwd");

//Erstellen der Verbindung
// achtung: wenn hier Fehlermeldung kommt wegen fehlendem Oracle-treiber --->
//im Agent müssen die Klassen als JArdatei eingehängt sein, wird unter 'Projekt bearbeiten' angezeigt, notfalls auf OracleHomeopage suchen
   logEvent("vor Driver " + System.currentTimeMillis());       
   DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
   logEvent("vor conn  " + System.currentTimeMillis());
   conn = DriverManager.getConnection("jdbc:oracle:thin:@"+strOracleServer, strOracleUser, strOraclePwd);  //Aufbau Verbindung

if (conn.isClosed())
            logEvent("Oracle Connection is not open yet.");
                  stmt = conn.createStatement();
         logEvent("Datenbankanbindung an ACAT erfolgreich hergestellt");
   
   
// Ermitteln der zu überprüfenden Dokumente

      terminalView = dbCurrent.getView("(luACATAbfrage)");
      terminalDoc = terminalView.getFirstDocument();

       while (terminalDoc != null) {
                 nextDoc = terminalView.getNextDocument(terminalDoc);
                
                checkyyyenInfo(terminalDoc);
                       
            terminalDoc.recycle();
            terminalDoc = nextDoc;
         
         } //Ende While

         logDoc.save(true,false);
         
         stmt.close();
          conn.close();
      } catch(Exception e) {
      
         e.printStackTrace();
      }      
      
      System.gc();
      
   } //Schließen Main
   

public void checkyyyenInfo(Document updateDoc)
   {
      
      try {
            logEvent("vor Abfrage " + System.currentTimeMillis());
            String common = updateDoc.getItemValueString("zzzName");
            rs = stmt.executeQuery ("SELECT * FROM " + strOracleView + " WHERE zzzName='"+common + "'");
                  logEvent(common + System.currentTimeMillis());
            if (rs.next())
            {
            String strxxxstelle = new String(rs.getString(3));
            String stryyyenstelle = new String(rs.getString(4));
         
            String strOldyyyenstelle = updateDoc.getItemValueString("yyyenstelle");
            String strOldxxxstelle = updateDoc.getItemValueString("xxxstelle");
            
            boolean result1 = strOldyyyenstelle.equals(stryyyenstelle );       
            boolean result2 = strOldxxxstelle.equals(strxxxstelle );   
            if ( result1 == false|| result2 == false)
                  {
                     fillyyyenInfo (updateDoc, stryyyenstelle, strxxxstelle);
                  }

         }
              
                rs.close();
     
         }
            
      catch(Exception e) {
         e.printStackTrace();
      }
   }// Schliessen checkyyyenstellenInfo    
   
      public void fillyyyenInfo(Document updateDoc, String stryyyenstelle,String strxxxstelle)
   {
      try {
      
         String common = updateDoc.getItemValueString("zzzName");
   
               updateDoc.replaceItemValue("xxxstelle",stryyyenstelle);
               updateDoc.replaceItemValue("yyyenstelle",strxxxstelle);   
         logEvent(common + System.currentTimeMillis());

   
                  updateDoc.save(true,false);   
           
         }
            
      catch(Exception e) {
         e.printStackTrace();
      }
   }// Schliessen FillyyyenstellenInfo    
   
   
   public void logEvent(String eventToBeLogged)
   {
      try {
      
         logCount++;
         logItem.appendToTextList(eventToBeLogged);
         if (logCount > 200)
         {
            logDocCount++;
            logCount=0;
            logDoc.save(true,false);
            logDoc = dbCurrent.createDocument();
            logDoc.replaceItemValue("Form","Log");
            logDoc.replaceItemValue("Lauf","Lauf vom: " + cal.get(Calendar.DATE)+"."+(cal.get(Calendar.MONTH)+1)+"."+cal.get(Calendar.YEAR)+" " + cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+" Uhr " + logDocCount + ". Teil");
            logDoc.replaceItemValue("Log","");
            logItem = logDoc.getFirstItem("Log");
         }
      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }

}

flaite:
Hi,

einiges ist suboptimal an dem Code.
Am besten du baust dir erstmal ein lesbares Logging für ad hoc Zeitmessungen ins log.
 

Eigenschaft: (unter Session session=null; )

--- Code: ---long lastMillis = System.currentTimeMillis();

--- Ende Code ---

Methode: (vor letzter schliessenden Klammer)

--- Code: ---public long getDifMillis() {
  long newMillis = System.currentTimeMillis();
  long dif = newMillis -  lastMillis;
  lastMillis = new Millis;
  return dif;
}

--- Ende Code ---

Dann kannst du im Code das für Logstatements verwenden.

ein guter Kandidat ist hier:

--- Code: ---while (terminalDoc != null) {
                 nextDoc = terminalView.getNextDocument(terminalDoc);
               
                checkyyyenInfo(terminalDoc);
                       
            terminalDoc.recycle();
            terminalDoc = nextDoc;
}

--- Ende Code ---
Vor dem recycle:

--- Code: ---logEvent("processing doc " + terminalDoc.getUniversalID() + " Zeitdif->" + getDifMillis + " milliseconds");

--- Ende Code ---

Ich vermute, dass am meisten Zeit für die ständig wiederholten Selects verbrauchst. Am meisten Optimierungsmöglichkeiten seh ich im SQL.
Vermutlich kannst du das ganze auf ein Statement verkürzen so der Art:

--- Code: ---SELECT spaltenDieDuBenötigstMitKommaGetrennt FROM " + strOracleView + " WHERE zzzName IN zusammenbauenDerBenötigtenWerteAlsKommaGetrennteListe.

--- Ende Code ---
Kann letzteres noch genauer ausführen, hab aber jetzt keine Zeit.

UND verwende die Klasse PreparedStatement und nicht Statement. Allein schon aus Sicherheitsgründen!
Was machst du, wenn Leute in dem Feld zzzname sowas wie "';Delete From eineTabelleInDerOracleDB eingeben  ;D

DAU-in:
Pro select werden 7 - 8 sekunden verbraten.

Das ist irgendwie ne ganze Menge  :-X

DAU-in:

--- Zitat von: Pitiyankee am 13.05.09 - 11:14:59 ---
Ich vermute, dass am meisten Zeit für die ständig wiederholten Selects verbrauchst. Am meisten Optimierungsmöglichkeiten seh ich im SQL.
Vermutlich kannst du das ganze auf ein Statement verkürzen so der Art:

--- Code: ---SELECT spaltenDieDuBenötigstMitKommaGetrennt FROM " + strOracleView + " WHERE zzzName IN zusammenbauenDerBenötigtenWerteAlsKommaGetrennteListe.

--- Ende Code ---


--- Ende Zitat ---

Die Liste: ist das jetzt ein String, der mit Komma getrennt die Werte enthält?
Oder läuft das auf einen Vektor hinaus?

flaite:
Pro Select? Das heisst der Agent führt mehrere Select statement durch und JEDES select dauert 7 bis 8 Sek?
Das ist nicht normal. Red mal mit einem DB Admin. Teste es mit einem SQL Client wie SQLPlus oder Squirrel von deinem Arbeitsplatz, ob es da auch so lange dauert, etc.

Eventuell - falls die Oracle.jar an den Agenten angehängt ist, kannst du auch mal versuchen die Oracle Treiber jar in das /lib/ext Verzeichnis des Servers tun. 


Select spaltenliste!!! in ('werta', 'wertB', ...)
Hab lang kein Oracle mehr gemacht, sollte aber da auch gehen.

Gruß Axel

Navigation

[0] Themen-Index

[#] Nächste Seite

Zur normalen Ansicht wechseln