2012-01-25 4 views
1

J'ai écrit une méthode qui rassemble des données à partir d'un serveur Oracle, les formats et crypte les données puis l'insère dans un serveur MS SQL. La méthode déplace environ 60000 enregistrements et prend un peu de temps et est un peu bâclée. Quelqu'un peut-il voir des endroits pour le nettoyer et le rendre plus rapide?méthode prend trop de temps

2 des zones que je vois pourraient avoir besoin d'améliorations sont lorsque le jeu de résultats est ajouté à la liste. Et lorsque la liste est insérée 1000 lignes à la fois dans la table MS SQL.

Voici le code:

public static void get_random_selection(Connection ora_conn, Connection sql_conn) throws Exception, SQLException{ 

    Statement sql_stmt = sql_conn.createStatement(); 
    Statement ora_stmt = ora_conn.createStatement(); 

    ResultSet sql_rs = null; 
    ResultSet ora_rs = null; 

    //Select the max QUARTER from RANDOM_SELECTION in MS SQL 
    sql_rs = sql_stmt.executeQuery("SELECT MAX(QUARTER) FROM RANDOM_SELECTION"); 

    sql_rs.next(); 
    int max_from_mssql = sql_rs.getInt(1); 

    ora_rs = ora_stmt.executeQuery("SELECT MAX(QUARTER) FROM RANDOM_SELECTION"); 

    ora_rs.next(); 
    int max_from_oracle = ora_rs.getInt(1); 

    //If the max_from_oracle is larger than max_from_mssql than the AL's and RL's in Oracle 
    //are fresher and need to be moved to MS SQL 
    //if (max_from_oracle > max_from_mssql){ 
    if(1==1){ 

     System.out.println("The RANDOM_SELECTION table in Oracle is more up to date than the RANDOM_SELECTION table in MS SQL."); 

     System.out.println("Retrieving RANDOM_SELECTION data from Oracle."); 

     //select items from RANDOM_SELECTION and DROPPER_CITY_BRK_2 that need to be moved 
     ora_rs = ora_stmt.executeQuery("select distinct(random_selection.randnum), " 
          + "random_selection.quarter, " 
          + "random_selection.ozip3, " 
          + "random_selection.boxid, " 
          + "random_selection.boxaddr, " 
          + "random_selection.locdesc, " 
          + "random_selection.loccity, " 
          + "random_selection.lastmf, " 
          + "random_selection.lastsat, " 
          + "random_selection.boxtype, " 
          + "random_selection.svcclas, " 
          + "random_selection.dropzip5, " 
          + "random_selection.dropper_id " 
         + "from random_selection " 
         + "where random_selection.dropper_id is not null " 
         + "and random_selection.quarter = " + max_from_oracle + " " 

        + "union " 

         + "select distinct(random_selection.randnum), " 
          + "random_selection.quarter, " 
          + "random_selection.ozip3, " 
          + "random_selection.boxid, " 
          + "random_selection.boxaddr, " 
          + "random_selection.locdesc, " 
          + "random_selection.loccity, " 
          + "random_selection.lastmf, " 
          + "random_selection.lastsat, " 
          + "random_selection.boxtype, " 
          + "random_selection.svcclas, " 
          + "random_selection.dropzip5, " 
          + "dropper_city_brk_2.dropper_id " 
         + "from random_selection, dropper_city_brk_2, dropper " 
         + "where random_selection.ozip3 = dropper_city_brk_2.zip3 " 
         + "and dropper.dropper_id = dropper_city_brk_2.dropper_id " 
         + "and dropper.active = 1 " 
         + "and dropper_city_brk_2.dropper_id <> 10002 " 
         + "and random_selection.quarter = " + max_from_oracle + " " 
         + "and random_selection.dropper_id is null"); 

     System.out.println("Retrieved RANDOM_SELECTION data from Oracle."); 

     List<String[]> random_selection = new ArrayList<String[]>(); 

     System.out.println("Assigning ResultSet to List."); 

     while (ora_rs.next()){ 
      random_selection.add(new String[]{ 
       ora_rs.getString("RANDNUM"), 
       ora_rs.getString("QUARTER"), 
       ora_rs.getString("OZIP3"), 
       ora_rs.getString("BOXID"), 
       ora_rs.getString("BOXADDR").replace("'"," "), 
       ora_rs.getString("LOCDESC") == null ? ora_rs.getString("LOCDESC") : ora_rs.getString("LOCDESC").replace("'",""), 
       ora_rs.getString("LOCCITY").replace("'", " "), 
       ora_rs.getString("LASTMF"), 
       ora_rs.getString("LASTSAT").equals("11:58pm") ? "null": ora_rs.getString("LASTSAT"), 
       ora_rs.getString("BOXTYPE"), 
       ora_rs.getString("SVCCLAS"), 
       ora_rs.getString("DROPZIP5"), 
       ora_rs.getString("DROPPER_ID")}); 

      System.out.println(ora_rs.getRow()); 
     } 

     System.out.println("Finished assigning ResultSet to List."); 

     //leading statement for the following loop 
     String query = "insert into random_selection " 
        + "(RANDNUM,QUARTER,OZIP3,BOXID,BOXADDR,LOCDESC,LOCCITY,LASTMF,LASTSAT,BOXTYPE,SVCCLAS,DROPZIP5,DROPPER_ID) VALUES"; 

     int jj = 0; 

     //loop through random_selection_array creating an INSERT statement to insert 999 entries at a time 
     //this is done to speed up the process 
     for(int ii = 0;ii<random_selection.size();ii++){ 

      String[] array_holder = random_selection.get(ii); 

      query = query 
        + "(" 
        + "'"+array_holder[0]+"'," 
        + "'"+array_holder[1]+"'," 
        + "'"+array_holder[2]+"'," 
        + "'"+array_holder[3]+"'," 
        + "'"+array_holder[4]+"'," 
        + "'"+array_holder[5]+"'," 
        + "'"+array_holder[6]+"'," 
        + "'"+array_holder[7]+"'," 
        + "'"+array_holder[8]+"'," 
        + "'"+array_holder[9]+"'," 
        + "'"+array_holder[10]+"'," 
        + "'"+array_holder[11]+"'," 
        + "'"+new sun.misc.BASE64Encoder().encode(encrypt(array_holder[12]))+"'),"; 

      //every 999 iterations enter here 
      if (jj > 998){ 
       //add |%| to the end of the string so that you can remove the final ',' 
       query = query+"|%|"; 
       query = query.replace(",|%|",""); 

       System.out.println(query); 

       //sql_stmt.executeUpdate(query); 
       query = "insert into random_selection (RANDNUM,QUARTER,OZIP3,BOXID,BOXADDR,LOCDESC,LOCCITY,LASTMF,LASTSAT,BOXTYPE,SVCCLAS,DROPZIP5,DROPPER_ID) VALUES"; 
       jj = 0; 
      } 
      jj++; 

      //the last few entries will be added one at a time to prevent nulls records from being inserted 
      if (ii > (random_selection.size()/999) * 999){ 
       //add |%| to the end of the string so that you can remove the final ',' 
       query = query+"|%|"; 
       query = query.replace(",|%|",""); 

       System.out.println(query); 

       //sql_stmt.executeUpdate(query); 
       query = "insert into random_selection (RANDNUM,QUARTER,OZIP3,BOXID,BOXADDR,LOCDESC,LOCCITY,LASTMF,LASTSAT,BOXTYPE,SVCCLAS,DROPZIP5,DROPPER_ID) VALUES"; 
      } 
     } 
    } 
} 

Le client veut s'abstenir de toute connexion ouverte entre les 2 serveurs.

+3

Probablement devrait être demandé ici: http://codereview.stackexchange.com/ – Max

+0

cette méthode fait beaucoup trop. c'est une douleur à suivre et pourrait utiliser un refactoring. BTW, pouvez-vous ajouter un serveur lié dans le serveur MS SQL pour faire tout cela dans la base de données? –

+2

@Mike - Le code doit absolument être en Java? Il est généralement très coûteux de lire toutes les données de la base de données source sur le réseau, de les traiter, puis de tout réécrire sur le réseau. Architecturalement, il serait plus efficace si les données étaient envoyées directement d'une base de données à une autre. Par exemple, vous pouvez créer un lien de base de données dans Oracle qui pointe vers SQL Server et demander à une procédure stockée Oracle d'écrire les données directement dans SQL Server sans le saut intermédiaire sur le serveur d'applications. –

Répondre

1

Le problème est probablement dû au grand nombre d'insertions effectuées sur le serveur MS SQL. Ce n'est pas très efficace de le faire.

La méthode correcte pour transférer des données entre deux bases de données (sans liaison) est de bcp lignes dans et hors. Tout d'abord, gardez à l'esprit que je n'ai aucune expérience avec BCP en dehors de sybase.

  1. Découvrez comment obtenir vos données au format MS bcp. Il y a plusieurs façons de le faire. Je voudrais essayer de créer une vue avec tous les requis dans l'oracle db et bcp à partir de là, mais cela peut ne pas être possible avec le truc encrypt().

  2. bcp in.

0

Tout d'abord, au lieu de deviner, vous devriez vraiment écrire à la console combien de temps il faut pour EFFECTIVEMENT chacun de ces domaines que vous pensez sont lents. :) Deuxièmement, vous devez utiliser une instruction préparée et utiliser addBatch et executeBatch. En C# j'utiliserais SqlBulkCopy, mais je ne pense pas que Java ait une classe comme ça, donc vous devriez essayer addBatch et executeBatch. Si c'est encore trop lent, alors je voudrais utiliser BULK INSERT: http://msdn.microsoft.com/en-us/library/ms188365.aspx