2016-09-19 2 views
4

Ich habe 200K Zeilen in einer einzigen Datenbanktabelle eingefügt werden. Ich habe versucht, jdbcTemplate.batchUpdate im Frühling zu verwenden, um Einfügung 10.000 pro Stapel zu tun. Dieser Prozess verbraucht jedoch zu viel Zeit (7 Minuten für 200 K-Zeilen). Also auf Datenbankseite, überprüfe ich die Anzahl der Zeilen von select count(*) from table_X eingefügt. Ich fand, dass die Anzahl der Zeilen leicht erhöht wurde, wenn 10K erwartet wurden. Kann jemand erklären, was Grund ist oder ist es etwas, das auf Datenbankseite konfiguriert werden sollte?Warum Frühling jdbcTemplate batchUpdate Zeile für Zeile einfügen

PS: Ich bin mit sybase ....

+0

Code anzeigen, verwenden Sie BatchPreparedStatementSetter? Verwenden Sie @Transactional Annotation auf Ihrem Dienst oder DAO? –

+0

@SheetalMohanSharma Anstatt Spring zu verwenden, wechselte ich zu nativem jdbc API und handhabt das Transactioin selbst. Es funktioniert jetzt. obwohl es immer noch sehr langsam ist .... –

+0

effektiv entfernte ich @Transactional Annotation, die das Problem verursachen könnte .... Aber ich entfernte es, um die Einfügung zu beschleunigen. ... Es hat nicht geholfen –

Antwort

1

Versuchen Sie unten für Verbindungszeicheneinstellung - useServerPrepStmts=false&rewriteBatchedStatements=true. Hab es nicht ausprobiert, aber es ist von meinen Lesezeichen. Sie können auf diesen Linien suchen.

Connection c = DriverManager.getConnection("jdbc:<db>://host:<port>/db?useServerPrepStmts=false&rewriteBatchedStatements=true", "username", "password"); 
+0

es sieht so aus, dass es doesn ' t Arbeit für Sybase :( –

+0

Hmm aber immer noch überprüfen, dass Post und Links in diesem Beitrag - es kann helfen –

+0

ja danke für Ihren Rat, ich werde diesen Beitrag aktualisieren, wenn ich eine Lösung finden –

5

Es gibt viele Ansätze im Web verfügbar. Leistung hängt direkt von dem

  1. Code, den Sie geschrieben haben
  2. JDBC-Treiber Sie
  3. Datenbank-Server und die Anzahl der von Ihnen verwendeten Verbindung
  4. Tabellenindizes verwenden führt zu Langsamkeit zum Einsetzen

Ohne auf Ihren Code zu schauen, kann jeder erraten, aber niemand kann die genaue Lösung finden.

Ansatz 1

//insert batch example 
public void insertBatch(final List<Customer> customers){ 

    String sql = "INSERT INTO CUSTOMER " + 
    "(CUST_ID, NAME, AGE) VALUES (?, ?, ?)"; 

    getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() { 

    @Override 
    public void setValues(PreparedStatement ps, int i) throws SQLException { 
     Customer customer = customers.get(i); 
     ps.setLong(1, customer.getCustId()); 
     ps.setString(2, customer.getName()); 
     ps.setInt(3, customer.getAge()); 
    } 

    @Override 
    public int getBatchSize() { 
     return customers.size(); 
    } 
    }); 
} 

Referenz

https://www.mkyong.com/spring/spring-jdbctemplate-batchupdate-example/

http://docs.spring.io/spring-framework/docs/3.0.0.M4/reference/html/ch12s04.html

Ansatz 2,1

//insert batch example 
public void insertBatch(final List<Customer> customers){ 
    String sql = "INSERT INTO CUSTOMER " + 
     "(CUST_ID, NAME, AGE) VALUES (?, ?, ?)"; 

    List<Object[]> parameters = new ArrayList<Object[]>(); 

    for (Customer cust : customers) { 
     parameters.add(new Object[] {cust.getCustId(), 
      cust.getName(), cust.getAge()} 
     ); 
    } 
    getSimpleJdbcTemplate().batchUpdate(sql, parameters); 
} 
Alternatively, you can execute the SQL directly. 

//insert batch example with SQL 
public void insertBatchSQL(final String sql){ 

    getJdbcTemplate().batchUpdate(new String[]{sql}); 

} 

refernce

https://www.mkyong.com/spring/spring-simplejdbctemplate-batchupdate-example/

Ansatz 2,2

public class JdbcActorDao implements ActorDao { 
    private SimpleJdbcTemplate simpleJdbcTemplate; 

    public void setDataSource(DataSource dataSource) { 
     this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); 
    } 

    public int[] batchUpdate(final List<Actor> actors) { 
     SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray()); 
     int[] updateCounts = simpleJdbcTemplate.batchUpdate(
      "update t_actor set first_name = :firstName, last_name = :lastName where id = :id", 
      batch); 
     return updateCounts; 
    } 

    // ... additional methods 
} 

Ansatz 2,3

public class JdbcActorDao implements ActorDao { 
    private SimpleJdbcTemplate simpleJdbcTemplate; 

    public void setDataSource(DataSource dataSource) { 
     this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); 
    } 

    public int[] batchUpdate(final List<Actor> actors) { 
     List<Object[]> batch = new ArrayList<Object[]>(); 
     for (Actor actor : actors) { 
      Object[] values = new Object[] { 
        actor.getFirstName(), 
        actor.getLastName(), 
        actor.getId()}; 
      batch.add(values); 
     } 
     int[] updateCounts = simpleJdbcTemplate.batchUpdate(
       "update t_actor set first_name = ?, last_name = ? where id = ?", 
       batch); 
     return updateCounts; 
    } 

    // ... additional methods 
} 

Ansatz 3: JDBC

dbConnection.setAutoCommit(false);//commit trasaction manually 

String insertTableSQL = "INSERT INTO DBUSER" 
      + "(USER_ID, USERNAME, CREATED_BY, CREATED_DATE) VALUES" 
      + "(?,?,?,?)"; 
PreparedStatement = dbConnection.prepareStatement(insertTableSQL); 

preparedStatement.setInt(1, 101); 
preparedStatement.setString(2, "mkyong101"); 
preparedStatement.setString(3, "system"); 
preparedStatement.setTimestamp(4, getCurrentTimeStamp()); 
preparedStatement.addBatch(); 

preparedStatement.setInt(1, 102); 
preparedStatement.setString(2, "mkyong102"); 
preparedStatement.setString(3, "system"); 
preparedStatement.setTimestamp(4, getCurrentTimeStamp()); 
preparedStatement.addBatch(); 
preparedStatement.executeBatch(); 

dbConnection.commit(); 

refernce

https://www.mkyong.com/jdbc/jdbc-preparedstatement-example-batch-update/

/*Happy Coding*/ 
+0

Vielen Dank für Ihre Antwort. Mein Code war Ansatz 3 mit nativen JDBC preparedstatement.Tatsächlich erfolgt die Einfügung effektiv durch Batch, die 10K Zeilen enthält.Aber 10k Zeilen tooks 25 bis 30 Sekunden zu beenden, was inakzeptabel ist :( –

+0

Ich benutze Sybase 15.5, und denke, es könnte ein Problem mit Sybase sein , weil ich mit PostgreSQL mit dem gleichen Code getestet habe.PraggreSQL dauert weniger als 1 Sekunde für 10K Zeilen.Ich hatte DBA Team um Rat gefragt.Thanks für Ihre Beispiele oben. –