Obtenir ExecuteBatch pour une exécution plus rapide
Je suis en train de lire un tableau à partir d'un serveur sybase, traiter les lignes de sortie et les résultats à une autre table. (Ci-dessous mon code)
Le code récupère le tableau assez rapide et les processus et tout aussi rapide (get à la partie où il envoie dans un délai de 30 secondes). Mais Quand je lance l'exécution du lot, il est assis là pendant 20 minutes avant de le terminer (pour info, j'ai un tableau que je suis en essais avec 8400 lignes).
Est-il un moyen plus efficace de faire cela? Je suis prête à comment je peux recevoir ou envoyer les requêtes (je peux créer une nouvelle table, mettre à jour une table, etc) -- je ne sais pas pourquoi c'est si lent (je suis sûr que les données < 1 MO et je suis sûr qu'il ne prenne pas le SQL server 20 minutes pour analyser 8400 lignes). Des idées?
Note: La raison pour cela est vraiment mauvais pour moi c'est que je dois analyser un tableau avec 1.2 MM lignes (ce tableau, je travaille à l'heure actuelle est une table de test avec 8400 lignes)
Connection conn = DriverManager.getConnection(conString, user, pass);
String sql = "SELECT id,dateid,attr from user.fromtable";
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
String sqlOut = "INSERT INTO user.mytabletest (id,attr,date,estEndtime) values (?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sqlOut);
int i=1;
while(rs.next())
{
int date = rs.getInt("dateid");
String attr = rs.getString("attr");
String id = rs.getString("id");
Time tt = getTime(date,attr);
Timestamp ts = new Timestamp(tt.getTime());
ps.setString(1, id);
ps.setString(2, attr);
ps.setInt(3, date);
ps.setTimestamp(4, ts);
ps.addBatch();
if(i % 10000 == 0)
{
System.out.println(i);
ps.executeBatch();
conn.commit();
ps.clearBatch();
}
i++;
}
System.out.println("sending "+(new Date()));
int[] results = ps.executeBatch();
System.out.println("committing "+(new Date()));
conn.commit();
System.out.println("done "+(new Date()));
Vous devez vous connecter pour publier un commentaire.
De travailler avec des lots de manière efficace, vous devez tourner à Validation automatique de l'option éteindre et l'allumer après l'exécution du traitement par lots (ou, alternativement, utiliser de connexion.méthode commit ())
J'ai eu ce même problème, enfin compris mais j'ai aussi n'a pas été en mesure de trouver la bonne explication n'importe où.
La réponse est simple, onu-conditionné insère
.executeBatch()
ne doit pas être utilisé. Ce mode batch est en train de faire est de faire plein de l'individu "insert into table x ..." états et c'est pourquoi il est lent. Toutefois, si les instructions d'insertion sont plus complexes, éventuellement avec des conditions qui affectent chaque ligne différemment, alors il pourrait être nécessaire d'insérer des remarques et de l'exécution du lot qui serait vraiment utile.Un exemple de ce qui fonctionne, essayez les solutions suivantes qui crée une instruction insert unique comme un PreparedStatement (mais même concept comme un objet Statement nécessiterait), et résout le problème de lenteur:
Ajouter ?rewriteBatchedStatements=true à la fin de votre url JDBC. Il va vous donner un sérieux l'amélioration de la performance. Notez que ceci est spécifique à MySql, n'aura aucun effet avec tous les autres pilotes JDBC.
Par exemple : jdbc:mysql://serveur:3306/db_name?rewriteBatchedStatements=true
Il a amélioré ma performance par plus de 15 fois
Il y a une solution commerciale de Progress DataDirect pour traduire JDBC lots dans la base de données native de chargement en masse protocole pour améliorer significativement les performances. Il est très populaire avec SQL Server, car il ne nécessite pas BCP. Je suis employée par le vendeur et écrit un blog sur comment bulk insert JDBC lots.