Массовая вставка из Java в Oracle

Мне нужно быстро вставить много маленьких строк в Oracle. (5 полей).

В MySQL я разбиваю вставки на группы по 100, затем использую один оператор insert для каждой группы из 100 вставок.

Но с Oracle обратная связь с пользователем заключается в том, что массовые вставки (где-то от 1000-30000) слишком медленные.

Есть ли аналогичный трюк, который я могу использовать для ускорения программных вставок из Java в Oracle?

Ответы

Ответ 1

Вы можете использовать модуль Spring DAO для пакетной вставки многих строк.

Пример, который вставляет коллекцию объектов Order в базу данных в одном обновлении:

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);
    }
}

Ответ 2

Вы не остаетесь, как вы передаете эти записи в базу данных. Лучший способ - использовать массив, поскольку это позволяет использовать Oracle множество отличных операционных операций FORALL.

В этом примере пакет имеет две процедуры. Один из которых заполняет коллекцию записей T23 (таблица, которая состоит из пяти числовых столбцов) и одна из которых вставляет записи в эту таблицу с использованием массива.

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>

Вот результат из нескольких прогонов:

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>

Я думаю, что вставка 100 000 записей за 0.15 секунды должна понравиться всем, кроме самых требовательных пользователей. Итак, вопрос в том, как вы подходите к своим вставкам?

Ответ 3

В настоящее время MySQL является Oracle, поэтому, возможно, более простым решением могло бы оставаться MySQL...

Если нет, то вы должны убедиться, что транзакция запущена до того, как вы запустите свою группу вставок, как только группа будет завершена, затем совершите транзакцию и начните новую транзакцию для следующей группы вставок.

Также проверьте ненужные определения индексов, которые могут замедлять время вставки.

Обновление...
Массовая вставка относится к последнему шагу ETL (Extract Transform Load), поэтому вы рассмотрели использование инструмента ETL на основе Java, например pentaho kettle или талант-студия.

Pentaho описывает свои средства загрузки Oracle Bulk здесь.

Быстрый google также показывает некоторые предварительные доказательства того, что Talend также имеет некоторую поддержку массовой загрузки Oracle.