Массовая вставка из 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.
Ответ 4
Я нашел хорошую страницу об этом. "Как выполнить групповую инструкцию INSERT.. RETURNING с Oracle и JDBC в DB2, Postgre и Oracle"