2010-04-26 22 views
14

J'ai besoin d'insérer rapidement de nombreuses petites lignes dans Oracle. (5 champs). Avec MySQL, je casse les inserts en groupes de 100, puis j'utilise une instruction d'insertion pour chaque groupe de 100 insertions. Mais avec Oracle, les commentaires des utilisateurs indiquent que les insertions de masse (entre 1000 et 30000) sont trop lentes.Insertion en masse de Java dans Oracle

Y at-il un truc similaire que je peux utiliser pour accélérer les insertions programmatiques de Java dans Oracle?

+0

créer des scripts de SQLPlus, pour Java/etc appeler plutôt que de le faire tout via Java. –

Répondre

0

Aujourd'hui, MySQL est Oracle donc peut-être une solution plus simple pourrait être de rester sur MySQL ...

Sinon, vous devez vous assurer que la transaction est démarré avant de commencer votre groupe d'inserts, une fois que le groupe est terminé, validez la transaction et lancez une nouvelle transaction pour le prochain groupe d'insertions.

Vérifiez également les définitions d'index inutiles susceptibles de ralentir le temps d'insertion.

Mise à jour ...
en vrac encartage fait référence à la dernière étape de ETL (Extrait Transform Load), alors avez-vous envisagé d'utiliser un outil ETL basé sur Java tels que pentaho kettle ou talend-studio.

Pentaho décrit ses installations de chargement Oracle Bulk here. Un rapide Google montre également une preuve préliminaire que Talend a également un certain soutien pour le chargement en vrac Oracle.

+4

MySQL n'est évidemment pas Oracle. La société est, mais le logiciel ne l'est pas. De plus, c'est le choix du client. Je préfère MySQL mais nous devons supporter les deux. –

+0

Juste pour confirmer, tout est déjà dans une seule transaction. –

+1

Le commentaire à propos de rester sur MySQL parce que c'est Oracle était censé être pris comme une blague ... sorte de ... là je vais encore ... – crowne

2

Vous ne restez pas comment vous transmettez ces enregistrements à la base de données. La meilleure façon est d'utiliser un tableau, car cela permet l'utilisation de l'abondance des opérations en vrac FORALL d'Oracle.

Cet exemple de package comporte deux procédures. Une qui remplit une collection d'enregistrements T23 (une table qui comprend cinq colonnes numériques) et une autre qui insère des enregistrements dans cette table en utilisant un tableau.

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> 

Voici la sortie de certains échantillons fonctionne:

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> 

Je pense que l'insertion de 100.000 enregistrements dans 0,15 secondes devrait plaire à tous, mais les plus exigeants des utilisateurs. Alors, la question est, comment abordez-vous vos inserts?

+1

Merci! Avec jdbc de Java, c'est ma seule contrainte. –

10

Vous pouvez utiliser le module DAO de Spring pour insérer plusieurs lignes par lots.

Un exemple qui insère une collection d'objets dans la commande base de données dans une mise à jour:

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

bon à savoir. Je n'utilise pas Spring ici, mais je vais garder cela à l'esprit. –

+0

Un avantage avec cette solution est qu'elle envoie toutes les données à la fin comme un gros paquet. Si vous exécutez des mises à jour pour chaque ligne, vous envoyez également le sur le réseau. JPA fournit également des solutions batch similaires à cette solution Spring. – Espen

Questions connexes