2010-04-26 53 views
14

Necesito insertar muchas filas pequeñas rápidamente en Oracle. (5 campos).inserción masiva de Java en Oracle

Con MySQL, rompo las inserciones en grupos de 100, luego uso una declaración de inserción para cada grupo de 100 inserciones.

Pero con Oracle, los comentarios de los usuarios es que las inserciones masivas (entre 1000 y 30000) son demasiado lentas.

¿Hay algún truco similar que pueda usar para acelerar las inserciones programáticas de Java en Oracle?

+0

scripts de construcción SQLPLUS, para Java/etc llamar en lugar de hacerlo todo a través de Java. –

Respuesta

0

Hoy en día es Oracle MySQL así que quizás una solución más simple podría ser la de permanecer en MySQL ...

Si no, entonces usted debe asegurarse de que se inicia la transacción antes de empezar su grupo de inserciones, una vez que el grupo está finalizado, luego comprometer la transacción e iniciar una nueva transacción para el siguiente grupo de inserciones.

También compruebe las definiciones de índice innecesarias que pueden estar ralentizando el tiempo de inserción.

Actualizado ...
inserción a granel se refiere a la última etapa del ETL (Extracto Transform Load), por lo que han considerado el uso de una herramienta ETL basada en Java, como pentaho kettle o talend-studio.

Pentaho describe sus instalaciones de carga Oracle Bulk here.

Un rápido google también muestra algunas pruebas preliminares de que Talend también tiene algo de soporte para la carga masiva de Oracle.

+4

MySQL obviamente no es Oracle. La compañía lo es, pero el software no lo es. Además, es la elección del cliente. Prefiero MySQL, pero necesitamos apoyar ambos. –

+0

Solo para confirmar, ya está todo dentro de una sola transacción. –

+1

El comentario sobre la permanencia en MySQL porque es Oracle estaba destinado a ser tomado como una broma ... más o menos ... allí voy de nuevo ... – crowne

2

No se queda cómo está pasando estos registros a la base de datos. La mejor manera es usar una matriz, ya que esto permite el uso de muchas operaciones ingeniosas FORALL bulk de Oracle.

Este paquete de ejemplo tiene dos procedimientos. Uno que rellena una colección de registros T23 (una tabla que comprende cinco columnas numéricas) y uno que a granel inserta registros en esa tabla usando una matriz.

SQL> create or replace package p23 as 
    2  type t23_nt is table of t23%rowtype; 
    3  function pop_array (p_no in number) 
    4   return t23_nt; 
    5  procedure ins_table (p_array in t23_nt); 
    6 end p23; 
    7/

Package created. 

SQL> create or replace package body p23 as 
    2 
    3  function pop_array (p_no in number) 
    4   return t23_nt 
    5  is 
    6   return_value t23_nt; 
    7  begin 
    8   select level,level,level,level,level 
    9   bulk collect into return_value 
10   from dual 
11   connect by level <= p_no; 
12   return return_value; 
13  end pop_array; 
14 
15  procedure ins_table 
16    (p_array in t23_nt) 
17  is 
18   s_time pls_integer; 
19  begin 
20 
21   s_time := dbms_utility.get_time; 
22 
23   forall r in p_array.first()..p_array.last() 
24    insert into t23 
25    values p_array(r); 
26 
27   dbms_output.put_line('loaded ' 
28     ||to_char(p_array.count())||' recs in ' 
29     ||to_char(dbms_utility.get_time - s_time) 
30     ||' csecs'); 
31  end ins_table; 
32 end p23; 
33/

Package body created. 

SQL> 

Aquí está la salida de algunas carreras de muestra:

SQL> declare 
    2  l_array p23.t23_nt; 
    3 begin 
    4  l_array := p23.pop_array(500); 
    5  p23.ins_table(l_array); 
    6  l_array := p23.pop_array(1000); 
    7  p23.ins_table(l_array); 
    8  l_array := p23.pop_array(2500); 
    9  p23.ins_table(l_array); 
10  l_array := p23.pop_array(5000); 
11  p23.ins_table(l_array); 
12  l_array := p23.pop_array(10000); 
13  p23.ins_table(l_array); 
14  l_array := p23.pop_array(100000); 
15  p23.ins_table(l_array); 
16 end; 
17/
loaded 500 recs in 0 csecs 
loaded 1000 recs in 0 csecs 
loaded 2500 recs in 0 csecs 
loaded 5000 recs in 1 csecs 
loaded 10000 recs in 1 csecs 
loaded 100000 recs in 15 csecs 

PL/SQL procedure successfully completed. 

SQL> 
SQL> select count(*) from t23 
    2/

    COUNT(*) 
---------- 
    119000 

SQL> 

Creo que la inserción de 100.000 registros en 0,15 segundos debería complacer a todos, pero el más exigente de los usuarios. Entonces, la pregunta es, ¿cómo te acercas a tus insertos?

+1

¡Gracias! Con jdbc de java, esa es mi única restricción. –

10

Puede usar el módulo DAO de Spring para insertar por lotes muchas filas.

Un ejemplo que inserta una colección de objetos de la Orden en la base de datos en un solo cambio:

public class OrderRepositoryImpl extends SimpleJdbcDaoSupport implements 
     OrderRepository { 

    private final String saveSql = "INSERT INTO orders(userid, username, coffee, coffeename, amount) " 
      + "VALUES(?, ?, ?, ?, ?)"; 

    public void saveOrders(final Collection<Order> orders) { 
     List<Object[]> ordersArgumentList = new ArrayList<Object[]>(orders 
       .size()); 

     Object[] orderArguments; 
     for (Order order : orders) { 
      orderArguments = new Object[] { order.getUserId(), 
        order.getUserName(), order.getCoffe(), 
        order.getCoffeeName(), order.getAmount() }; 

      ordersArgumentList.add(orderArguments); 
     } 

     getSimpleJdbcTemplate().batchUpdate(saveSql, ordersArgumentList); 
    } 
} 
+0

bueno saber. No estoy usando Spring aquí, pero lo tendré en cuenta. –

+0

Una ventaja con esta solución es que envía todos los datos al final como un paquete grande. Si está ejecutando actualizaciones para cada fila, envíelas también a través de la red. JPA también proporciona soluciones de lotes similares a esta solución Spring. – Espen

Cuestiones relacionadas