Primero, se introducen tres métodos de programación de inserción por lotes JDBC para compararlos. El contenido específico es el siguiente
La inserción por lotes JDBC se utiliza principalmente para la importación y registro de datos porque los registros generalmente se escriben primero en el archivo.
Utilicé el controlador JDBC de MySQL 5.1.5 para probar tres métodos más utilizados
Método 1: Use preparado para agregar lotes
intente {class.forname ("com.mysql.jdbc.driver"); conn = drivermanager.getConnection (o_url, nombre de usuario, contraseña); conn.setAutOcommit (falso); String sql = "insertar adlogs (IP, sitio web, yyyymmdd, hora, objeto_id) valores (?,?,?,?,?)"; Preparado Perst = Conn.PrepareStatement (SQL, resultSet.Type_Scroll_Sensitive, ResultSet.concur_read_only); para (int x = 0; x <size; x ++) {prest.setString (1, "192.168.1.1"); prest.setstring (2, "localhost"); prest.setstring (3, "20081009"); prest.setint (4, 8); prest.setString (5, "11111111"); prest.addbatch (); } prest.executeBatch (); conn.commit (); conn.close (); } Catch (Sqlexception ex) {logger.getLogger (mylogger.class.getName ()). log (nivel.severe, null, ex); } Catch (ClassNotFoundException ex) {logger.getLogger (mylogger.class.getName ()). log (nivel.severe, null, ex); } Explique el significado de los siguientes dos parámetros al construir una declaración:
El primer parámetro especifica el tipo de resultado de resultados. Las opciones son:
Type_forward_only: tipo predeterminado. El acceso directo solo se permite una vez y no se verá afectado por los cambios realizados por otros usuarios en la base de datos.
Type_scroll_insensitive: permite el movimiento hacia adelante o hacia atrás en la lista, e incluso un posicionamiento específico, como moverse al cuarto registro en la lista o mover dos registros hacia atrás desde la posición actual. No se verá afectado por los cambios realizados por otros usuarios en la base de datos.
Type_scroll_sensitive: como type_scroll_insensitive, el posicionamiento está permitido en los registros. Este tipo se ve afectado por los cambios realizados por otros usuarios. Si el usuario elimina un registro después de ejecutar la consulta, ese registro desaparecerá del conjunto de resultados. Del mismo modo, los cambios en los valores de datos se reflejarán en el resultado de resultados.
El segundo parámetro establece la concurrencia de ResultSet, que determina si el conjunto de resultados se puede actualizar. Las opciones son:
Concur_read_only: este es el valor predeterminado, especificado que no se puede actualizar
ResultSet concur_updatable: especifica que el setset se puede actualizar
Método 2: Use la declaración para agregar el método por lotes
conn.setAutOcommit (falso); Declaración stmt = conn.createStatement (resultset.type_scroll_sensitive, resultset.concur_read_only); for (int x = 0; x <size; x ++) {stmt.addbatch ("inserte en adlogs (ip, sitio web, yyyymmdd, hour, object_id) valores ('192.168.1.3', 'localhost', '20081009', 8, '23123')"); } stmt.executeBatch (); conn.commit ();Método 3: Use la declaración directamente
conn.setAutOcommit (falso); Declaración stmt = conn.createStatement (resultset.type_scroll_sensitive, resultset.concur_read_only); for (int x = 0; x <size; x ++) {stmt.execute ("inserte en adlogs (ip, sitio web, yyyymmdd, hour, object_id) valores ('192.168.1.3', 'localhost', '20081009', 8, '23123')"); } conn.commit (); El tiempo de prueba promedio para insertar 100,000 datos utilizando el método anterior es:
Método 1: 17.844s
Método 2: 18.421S
Método 3: 16.359S
Se puede ver que la inserción de las declaraciones de lotes JDBC no solo no mejora el rendimiento, sino que es más lento que cuando no se usa lote. Por supuesto, esto puede estar relacionado con el método de implementación de los controladores específicos de JDBC. El archivo adjunto es mi código de prueba, que se puede usar para ejecutarse en mi computadora.
Al realizar la inserción por lotes, lo más importante es cancelar automáticamente el envío, por lo que no debería importar si se usa o no la sintaxis por lotes de JDBC.
conn.setAutOcommit (falso)
Personalmente, creo que el primer método es el más conveniente y práctico.
Ejemplo de explicación de los datos de inserción de lotes JDBC :
Recientemente, cuando estaba trabajando en un programa para importar datos de Excel a una base de datos, me estaba preparando para usar la inserción de lotes JDBC debido a la gran cantidad de datos. Entonces se usa prepararestatem.Addbatch (); Cuando se agregan 1W de datos, se realiza la operación de inserción, se utiliza preparado Statement.exCuteBatch (). Pensé que esto sería rápido, pero me llevó más de 30 minutos insertar 65,536 datos, lo que estaba completamente más allá de mis expectativas. Entonces les pregunté a mis colegas cómo procesaron este tipo de importación de datos a gran escala. Descubrí que también usaban el procesamiento de inserción de lotes JDBC, pero a diferencia de mí, usaron con.setAutOcommit (falso); luego prepareStatement.exCuteBatch () y luego ejecutó con.commit (); Así que lo intenté de nuevo, ¿qué es un milagro? Solo tomó media hora importar estos datos, y después de agregar estas dos oraciones, solo tardó 15 segundos en completarlos. Así que revisé el motivo y encontré la siguiente explicación en línea:
* Al importar datos a innodb, asegúrese de que MySQL no tenga habilitado el modo de autocommitio porque eso
Requiere una descarga de registro en el disco para cada inserto. Para deshabilitar el autocommit durante su operación de importación, rodeárselo con
Establecer declaraciones de autocommit y confirmar:
Establecer autocommit = 0;
... declaraciones de importación SQL ...
COMPROMETERSE;
La primera vez, es precisamente porque no hay setAutOcommit (falso); Para cada declaración de inserción, se generará un registro en el disco. Por lo tanto, aunque se establece el inserto por lotes, su efecto es como un solo inserto, lo que resulta en una inserción muy lenta.
Algunos de los códigos son los siguientes:
Cadena sql = "insertar en la tabla *****"; con.setAutOcommit (false); ps = con.preparestatement (sql); para (int i = 1; i <65536; i ++) {ps.addbatch (); // insertar registros 1W una vez if (i % 10000 == 0) {ps.ExecuteBatch (); con.commit (); }} // inserta menos de 1W datos Ps.ExecuteBatch (); con.commit ();Lo anterior es solo un guarnición, y luego es seguido de "servir":
1. Probar datos de escritura por lotes
Long Start = System.CurrentTimemillis (); Daorecord daorecord = new Daorecord (); List <t> list = new ArrayList <T> (); para (int i = 1; i <= 1000; i ++) {for (int j = 1; j <= 1000; j ++) {t t = new t (); t.seti (i); t.setj (j); list.add (t); }} daorecord.insertbatch (lista); System.out.println ("consumo de tiempo:" + (System.CurrentTimemillis ()-inicio) + "MS"); 2. Prueba de datos de escritura por lotes
public void insertBatch (list <t> list) {string sql = "insertar en valores t (go, back) (?,?)"; Dbhelper dbh = nuevo dbHelper (SQL); Conexión conn = dbh.returnConn (); Pruebe {conn.setAutOcommit (false); // Tenga en cuenta que esta oración debe ser falsa, consulte la primera referencia preparada 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 Generado automáticamente BLOCK E.PRINTSTACKTRACE (); }}Tabla de datos:
Resultados experimentales:
Lo anterior se trata de este artículo, espero que sea útil para el aprendizaje de todos.