Premièrement, trois méthodes de programmation d'insertion par lots JDBC sont introduites pour les comparer. Le contenu spécifique est le suivant
L'insertion par lots JDBC est principalement utilisée pour l'importation et la journalisation des données car les journaux sont généralement écrits dans le fichier en premier.
J'ai utilisé le pilote JDBC de MySQL 5.1.5 pour tester trois méthodes plus couramment utilisées
Méthode 1: Utilisez PréparedStatement pour ajouter des lots
essayez {class.forname ("com.mysql.jdbc.driver"); Conn = driverManager.getConnection (o_url, nom d'utilisateur, mot de passe); Conn.SetAutoCommit (false); String sql = "INSERT ADLOGS (IP, Site Web, YyyyMMDD, Hour, Object_id) VALEURS (?,?,?,?,?)"; PréparéStatement perst = conn.preparestatement (sql, resultSet.type_scroll_sentive, resultset.concur_read_only); pour (int x = 0; x <size; x ++) {prest.SetString (1, "192.168.1.1"); prest.setsstring (2, "localhost"); prest.setsstring (3, "20081009"); prest.sent (4, 8); prest.SetString (5, "11111111"); prest.addbatch (); } prest.executeBatch (); Conn.Commit (); conn.close (); } catch (sqlexception ex) {logger.getLogger (myLogger.class.getName ()). Log (niveau.severe, null, ex); } catch (classNotFoundException ex) {Logger.getLogger (myLogger.class.getName ()). Log (niveau.severe, null, ex); } Expliquez la signification des deux paramètres suivants lors de la construction d'une déclaration:
Le premier paramètre spécifie le type de résultat. Les options sont:
Type_Forward_only: type par défaut. L'accès à terme n'est autorisé qu'une seule fois et ne sera pas affecté par les modifications apportées par d'autres utilisateurs à la base de données.
TYPE_SCROLL_INSENSITION: permet un mouvement vers l'avant ou vers l'arrière dans la liste, et même le positionnement spécifique, comme passer au quatrième enregistrement dans la liste ou déplacer deux enregistrements en arrière à partir de la position actuelle. Il ne sera pas affecté par les modifications apportées par d'autres utilisateurs à la base de données.
TYPE_SCROLL_SENSITION: Comme Type_Scroll_insensitive, le positionnement est autorisé dans les enregistrements. Ce type est affecté par les modifications apportées par d'autres utilisateurs. Si l'utilisateur supprime un enregistrement après l'exécution de la requête, cet enregistrement disparaîtra du résultat. De même, les modifications des valeurs de données seront reflétées dans le résultat.
Le deuxième paramètre définit la concurrence du résultat, qui détermine si le résultat peut être mis à jour. Les options sont:
Concur_read_only: il s'agit de la valeur par défaut, spécifiée qu'elle ne peut pas être mise à jour
ResultSet CONCUR_UPDATable: Spécifie que le résultat peut être mis à jour
Méthode 2: Utilisez l'instruction pour ajouter la méthode par lots
Conn.SetAutoCommit (false); Instruction STMT = Conn.CreatEstatement (resultSet.Type_Scroll_Sensitive, resultSet.CUCUR_READ_ONLY); pour (int x = 0; x <size; x ++) {stmt.addbatch ("insérer dans les valeurs adlogs (ip, site Web, yyyymmdd, hour, object_id) ('192.168.1.3', 'localhost', '20081009', 8, '23123')"); } stmt.ExecuteBatch (); Conn.Commit ();Méthode 3: Utilisez l'instruction directement
Conn.SetAutoCommit (false); Instruction STMT = Conn.CreatEstatement (resultSet.Type_Scroll_Sensitive, resultSet.CUCUR_READ_ONLY); pour (int x = 0; x <size; x ++) {stmt.execute ("insérer dans les valeurs Adlogs (IP, site Web, yyyymmdd, hour, object_id) ('192.168.1.3', 'localhost', '20081009', 8, '23123')"); } conn.Commit (); Le temps de test moyen pour insérer 100 000 éléments de données en utilisant la méthode ci-dessus est:
Méthode 1: 17.844S
Méthode 2: 18.421S
Méthode 3: 16.359S
On peut voir que l'insertion des instructions par lots JDBC n'améliore pas les performances, mais est plus lente que lorsqu'aucun lot n'est utilisé. Bien sûr, cela peut être lié à la méthode de mise en œuvre des pilotes spécifiques de JDBC. La pièce jointe est mon code de test, qui peut être utilisé pour s'exécuter sur mon ordinateur.
Lorsque vous effectuez une insertion par lots, la chose la plus importante est d'annuler automatiquement la soumission, il ne devrait donc pas avoir d'importance si la syntaxe par lots de JDBC est utilisée ou non.
Conn.SetAutoCommit (false)
Je pense personnellement que la première méthode est la plus pratique et la plus pratique.
Exemple d'explication des données d'insertion par lots JDBC :
Récemment, lorsque je travaillais sur un programme pour importer des données Excel dans une base de données, je me préparais à utiliser l'insertion par lots JDBC en raison de la grande quantité de données. Ainsi, préparestaça.addbatch () est utilisé; Lorsque des éléments de données 1W sont ajoutés, l'opération d'insertion est effectuée, préparéStatement.ExECuteBatch () est utilisé. Je pensais que ce serait rapide, mais il m'a fallu plus de 30 minutes pour insérer 65 536 données, ce qui était complètement au-delà de mes attentes. J'ai donc demandé à mes collègues comment ils avaient traité ce type d'importation de données à grande échelle. J'ai trouvé qu'ils utilisaient également le traitement de l'insertion par lots JDBC, mais contrairement à moi, ils ont utilisé con.setAutoCommit (false); puis préparéStatement.ExecuteBatch () puis exécuté con.Commit (); Alors j'ai réessayé, qu'est-ce qu'un miracle? Il a fallu une demi-heure pour importer ces données, et après avoir ajouté ces deux phrases, il n'a fallu que 15 secondes pour la terminer. J'ai donc vérifié la raison et trouvé l'explication suivante en ligne:
* Lors de l'importation de données dans InNODB, assurez-vous que MySQL n'a pas de mode AutoCommit activé parce que cela
Nécessite un journal à rlus sur le disque pour chaque insert. Pour désactiver l'autocommit pendant votre opération d'importation, entourez-le de
Définissez les déclarations AutoCommit et commises:
Définir AutoCommit = 0;
... Instructions d'importation SQL ...
COMMETTRE;
La première fois, c'est précisément parce qu'il n'y a pas de setAutoCommit (false); Pour chaque instruction d'insertion, un journal sera généré sur le disque. Par conséquent, bien que l'insert par lots soit défini, son effet est comme un seul insert, ce qui entraîne une insertion très lente.
Certains codes sont les suivants:
String SQL = "INSERT INTO TABLE *****"; CON.SetAutoCommit (false); ps = Con.PrepareStatement (SQL); pour (int i = 1; i <65536; i ++) {ps.addbatch (); // Insérez 1W enregistre une fois if (i% 10000 == 0) {ps.ExecuteBatch (); Con.Commit (); }} // insérer moins de 1w de données ps.ExecuteBatch (); Con.Commit ();Ce qui précède n'est qu'un plat d'accompagnement, puis "servir" est suivi de:
1. Tester les données d'écriture par lots
Long start = System.CurrentTimemillis (); Daorecord daorecord = new daorecord (); List <T> list = new ArrayList <T> (); pour (int i = 1; i <= 1000; i ++) {pour (int j = 1; j <= 1000; j ++) {t t = new t (); t.seti (i); t.setj (j); list.add (t); }} daorecord.insertbatch (list); System.out.println ("Le temps qui prend du temps:" + (System.Currenttimemillis () - START) + "MS"); 2. Test de données d'écriture par lots
public void insertBatch (list <t> list) {String sql = "insérer dans les valeurs t (go, dos) (?,?)"; DbHelper dbh = new dbhelper (sql); Connexion conn = dbh.returnConn (); essayez {conn.setautoCommit (false); // notez que cette phrase doit être fausse, voir la première référence préparée PS = conn.preparestatement (SQL); for (int i = 0; i <list.size (); i ++) {ps.setInt (1, list.get (i) .geti ()); ps.SetInt (2, list.get (i) .getj ()); ps.AddBatch (); if (i% 10000 == 0) {ps.ExecuteBatch (); Conn.Commit (); }} ps.ExecuteBatch (); Conn.Commit (); conn.close (); } catch (sqlexception e) {// todo généré automatiquement le bloc de capture e.printStackTrace (); }}Tableau de données:
Résultats expérimentaux:
Ce qui précède concerne cet article, j'espère qu'il sera utile à l'apprentissage de tout le monde.