2010-09-14 8 views
1

J'ai une requête comme celle-ci et je me demandais quel type de SQL est produit en batch un PreparedStatement.En Java, comment PreparedStatement fonctionne pour la requête suivante

INSERT INTO table1 (id, version, data) 
    VALUES (?, ?, ?) 
    ON DUPLICATE KEY UPDATE 
    table1.data = IF(table1.version > table2.version, table1.data, table2.data), 
    table1.version = IF(table1.version > table2.version, table1.version, table2.version) 

La question est, sera-t résoudre ce à une copie de toute cette chaîne SQL pour chaque ligne dans le lot ou entend-elle faire quelque chose comme:

INSERT INTO table1 (id, version, data) 
    VALUES (a1, b1, c1), (a2, b2, c2), (a3, b3, c3), ... 
    ON DUPLICATE KEY UPDATE 
    table1.data = IF(table1.version > table2.version, table1.data, table2.data), 
    table1.version = IF(table1.version > table2.version, table1.version, table2.version) 

Sinon, quelle est la performance implication et comment puis-je l'écrire de telle sorte que je peux lot plusieurs de ces instructions INSERT..UPDATE en utilisant PreparedStatement sans encourir une pénalité de performance?

Répondre

2

Une instruction préparée insère simplement les valeurs positionnelles que vous avez entrées dans une instruction répétitive qui n'a pas besoin d'être analysée à chaque fois. Donc, votre deuxième formulaire nécessiterait simplement des paramètres N * 3 et ne vous donnerait aucune amélioration de la vitesse d'une instruction préparée. Pour répéter des instructions, vous voulez utiliser addTobatch. Fondamentalement vous préparez l'instruction, (par exemple "UPDATE ...???" Et puis ajoutez 3 paramètres à la fois, et exécutez le lot tout à la fois.)

J'avais l'habitude d'employer quelque chose comme ceci comme utilité à emballer le désordre de ceci. Donc vous feriez juste quelque chose comme

SQLBatchHandler h = new SQLBatchHandler(conn, "UPDATE ... WHERE ? ? ? ... "); 
    h.addToBatch(x, y,z); 
    h.addToBatch(x2,y2,z2); 
    ... 
    h.flush(); 



public class SQLBatchHandler { 
    public static int   MAX_BATCH_SIZE = 500; 
    public String   query; 
    private Connection  conn; 
    private PreparedStatement ps; 
    private int    batch_ct; 

    public SQLBatchHandler(Connection c, String query) throws SQLException 
     { 
     conn = c; 
     this.query = query; 
     ps = conn.prepareStatement(query); 
    } 

    /** 
    * add this row to the batch and handle the commit if the batch size 
    * exceeds {@link #MAX_BATCH_SIZE} 
    * 
    * @param values row values 
    * @throws SQLException 
    */ 
    public void addToBatch(Object ... values) throws SQLException 
    { 
     int i = 0; 
     for (Object value: values) 
     { 
      ps.setObject((++i), value); 
     } 
     add(); 
    } 

    private void add() throws SQLException 
    { 
     ps.addBatch(); 
     if ((++batch_ct) > MAX_BATCH_SIZE) 
     { 
      ps.executeBatch(); 
      batch_ct = 0; 
     } 
    } 

    /** 
    * Commit any remaining objects and close. 
    * 
    * @throws SQLException On statement close error. 
    */ 
    public void flush() throws SQLException 
    { 
     if (batch_ct == 0) { return; } 
     try 
     { 
      ps.executeBatch(); 
     } 
     catch (SQLException e) 
     { 
      throw e; 
     } 
     finally 
     { 
      if (ps != null) 
      { 
       ps.close(); 
      } 
     } 
    } 
} 
Questions connexes