2011-02-04 13 views
11

Tengo una aplicación Java con un back-end de base de datos Oracle en el que necesito insertar varias filas. He visto la discusión sobre inserting multiple rows into Oracle, pero también estoy interesado en cómo se ve afectado el rendimiento cuando se lanza JDBC en la mezcla.Rendimiento Oracle y JDBC: INSERTAR TODOS vs preparedStatement.addBatch

veo algunas posibilidades:

Opción 1: Utilice un singe-fila de inserción PreparedStatement y ejecutarlo varias veces:

String insert = "Insert into foo(bar, baz) values (?, ?)"; 
PreparedStatement stmt = conn.prepareStatement(insert); 
for(MyObject obj : someList) { 
    stmt.setString(1, obj.getBar()); 
    stmt.setString(2, obj.getBaz()); 
    stmt.execute(); 
} 

Opción 2: Construir un Oracle insertar todos afirmación:

String insert = "INSERT ALL " + 
    "INTO foo(bar, baz), (?, ?) " + 
    "INTO foo(bar, baz), (?, ?) " + 
    "SELECT * FROM DUAL"; 
PreparedStatement stmt = conn.prepareStatement(insert); 
int i=1; 
for(MyObject obj : someList) { 
    stmt.setString(i++, obj.getBar()); 
    stmt.setString(i++, obj.getBaz()); 
} 
stmt.execute(); 

Opción 3: uso la funcionalidad addBatch de PreparedStatement:

String insert = "Insert into foo(bar, baz) values (?, ?)"; 
PreparedStatement stmt = conn.prepareStatement(insert); 
for(MyObject obj : someList) { 
    stmt.setString(1, obj.getBar()); 
    stmt.setString(2, obj.getBaz()); 
    stmt.addBatch(); 
} 
stmt.execute(); 

supongo que otra posibilidad sería la creación de un archivo CSV y utilizar el cargador de SQL, pero no estoy seguro de que sería realmente más rápido si se añade a la sobrecarga de crear el archivo CSV ...

Entonces, ¿qué opción sería la más rápida?

+2

Por favor, comparta los resultados de sus mediciones. Tenga en cuenta que Oracle tiene una limitación en el tamaño del lote. Si no me equivoco, son 1000 registros a la vez, por lo que debe llamar a 'executeBatch()' cada 1000 registros. Relacionado: http://stackoverflow.com/questions/2467125/reusing-a-preparedstatement-multiple-times – BalusC

+0

He usado con éxito tamaños de lote de 2500, pero no he visto una mejora real en el rendimiento más allá de un tamaño de 500 –

Respuesta

7

Utilice la funcionalidad addBatch de PreparedStatement para cualquier cantidad inferior a 1,000,000 de filas.

Cada componente adicional que agregue a su código aumenta las dependencias y los puntos de falla. Si sigues esa ruta (tablas externas, cargador sql, etc.) asegúrate de que realmente valga la pena.

Serializar datos en un archivo csv, moverlo a una ubicación legible por la base de datos tomará fácilmente un segundo más o menos. Durante ese tiempo, podría haber insertado 20,000 filas si simplemente lo absorbiera y comenzara a insertar con JDBC.

2

SQL Loader parece ser una mejor manera, incluso sin carga de ruta directa, pero es difícil de mantener. Inserte por lotes 2-4 veces más rápido que las instrucciones de inserción individual. Inserta todo como una inserción por lotes, y ambas cosas serían más rápidas que la implementación de PL/SQL.

También le recomendamos leer this AskTom topic.

+0

en mi caso, la inserción del lote fue más de 100 veces más rápida que la inserción de una sola línea. –

1

El uso del lote puede ser transparente para un programador. Aquí está una de here citan:

Ajuste del Lote Valor de Enlace

Puede especificar un valor por defecto para cualquier lote de Oracle prepara declaración en su conexión de Oracle. > Para hacer esto, use el método setDefaultExecuteBatch() del objeto OracleConnection. Por ejemplo, el siguiente código establece el valor de lote predeterminado en 20 para todos los objetos de declaración preparados asociados con el objeto de conexión de conexión:

(conexión de Oracle) conn) .setDefaultExecuteBatch (20);

Aunque esto establece el valor por lotes predeterminado para todas las declaraciones preparadas de la conexión, puede anularlo llamando a setDefaultBatch() en sentencias individuales preparadas por Oracle.

El valor del lote de conexión se aplicará a los objetos de declaración creados después de establecer este valor de lote.