Статьи

Использование функций вставки JDBC в Oracle

Вступление

В этой статье я покажу пример использования функций массовой вставки JDBC, поддерживаемых Oracle — и специфичных для Oracle.

Более подробную информацию о том, почему можно прибегнуть к использованию массовых вставок в целом, например, о соображениях производительности, когда этого требуют определенные обстоятельства, см. В статье JCG « Пример пакетной вставки JDBC », опубликованной Джурманой Брахмой, опубликованной 12 апреля 2015 года.

Там г-жа Брахма приводит 3 примера того, как выполнить это умение в JDBC с использованием MySQL, но специфичный для Oracle способ, который я покажу в этой статье, можно рассматривать как нечто среднее между ее вторым и третьим примером, например, гибридом между PreparedStatement и Пакетная партия.

Установка Oracle

Чтобы использовать специфичные для Oracle функции, поддерживающие массовую вставку JDBC, которые я покажу в этом примере, сначала необходимо создать пару пользовательских типов в базе данных Oracle.

Первый тип сопоставляется с записью в таблице, в которую выполняется массовая вставка, а второй тип сопоставляется с массивом переменных первого типа. Другими словами, вы можете думать о первом типе как о строке в таблице, а второй тип — это просто массив этих строк.

Именно этот массив вы массово вставляете в таблицу, используя специфичные для Oracle функции, которые поддерживают массовые операции JDBC, которые я продемонстрирую в этой статье.

Поэтому первое, что нужно создать в этом примере, — это таблица в Oracle ( см. Листинг 1 ниже ).

1
2
3
4
5
6
7
8
DROP TABLE "SYSTEM"."EMPLOYEE";
CREATE TABLE "SYSTEM"."EMPLOYEE"
   "FIRST_NAME" VARCHAR2(20 BYTE),
      "LAST_NAME" VARCHAR2(20 BYTE),
      "EMP_NO" NUMBER,
      "JOIN_DATE" DATE
   )
TABLESPACE "SYSTEM" ;

Листинг 1. DDL для создания таблицы «Сотрудник»

Эта таблица является упрощенной версией таблицы Employees в схеме HR, которую Oracle использует для своих примеров в Application Express. Обратите внимание, что пример в листинге 1 создан пользователем системы — что нереально для реального использования, но здесь будет достаточно для наших целей, например, в полях, таких как число и дата, помимо varchar2 есть сочетание типов SQL ,

Затем нам нужно создать пользовательский тип, который отображается на строку в этой таблице ( см. Листинг 2 ниже ), например, обратите внимание, что он имеет прямую корреляцию с полями в таблице Employee в листинге 1.

1
2
3
4
5
6
7
create or replace
TYPE t_type AS OBJECT (
  first_name varchar2(20),
  last_name varchar2(20),
  emp_no number,
  join_date date
);

Листинг 2. PL / SQL для создания объекта « t_type »

Затем нам нужно создать еще один пользовательский тип, который сопоставляется с массивом переменных первого типа ( см. Листинг 3 ниже ).

1
2
3
create or replace
type tb_t_type
as varray (1000000) of t_type;

Листинг 3. PL / SQL для создания объекта « tb_t_type »

Обратите внимание, что здесь мы определяем, что этот массив имеет максимальный размер 1 миллион. Вы можете отрегулировать этот размер в соответствии со своими потребностями — конечно, в рамках собственных ограничений ресурсов — но мы действительно добавим 1 миллион записей в нашем примере JDBC здесь.

Наконец, нам нужно будет создать хранимую процедуру, которая будет вызываться массовой операцией ( см. Листинг 4 ниже ).

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
create or replace
procedure add_employees (emparray in tb_t_type) as
 
begin
  forall i in emparray.first .. emparray.last
    insert into EMPLOYEE( first_name,               
                          last_name,
                          emp_no,
                          join_date )
         
    values( emparray(i).first_name,
            emparray(i).last_name,
            emparray(i).emp_no,
            emparray(i).join_date );
 
end add_employees;

Листинг 4. PL / SQL для создания хранимой процедуры add_employees

Обратите внимание на использование идиомы forall в этом PL / SQL, которая делает фактическую операцию массовой вставки примерно на половину порядка быстрее, чем это возможно, если использовать только простой цикл for. В частности, в моих собственных демонстрационных прогонах я заметил, что идиома дает результаты примерно в 5 раз быстрее.

Примечание: в этом примере я использовал Oracle Database Express Edition 11g Release 2 на ноутбуке Dell под управлением Windows 7 Home Premium с процессором Intel i5 с частотой 1,7 ГГц и 8 ГБ ОЗУ. Для драйвера Oracle JDBC я использовал ojdbc6.jar .

JDBC

Завершив настройку Oracle, теперь мы можем посмотреть, как использовать специфичные для Oracle функции, поддерживающие операции массовой вставки JDBC ( см. Листинг 5 ниже ).

Pic1

Листинг 5. Пример Java, иллюстрирующий специфичные для Oracle функции, поддерживающие операции массовой вставки JDBC

Анализ

Обратите внимание на операторы импорта в строках 2-4, т. ojdbc6.jar специфичные для Oracle типы, как определено в ojdbc6.jar , и, как я уже ojdbc6.jar , ранее в этом примере использовались специфичные для Oracle функции для массовой вставки JDBC.

Как указано в комментарии к строке 12, первое, что нужно сделать, это получить наш источник данных. Обратите внимание, что для строк 14-16 вам нужно будет заменить ваши собственные значения для хоста, порта и идентификатора службы («sid») — хотя, если вы используете порт по умолчанию, это будет просто 1521.

В строках 22-23 мы определяем массив Oracle STRUCT, который сопоставляется с пользовательским типом, который мы создали ранее в нашей базе данных Oracle, « tb_t_type » ( см. Листинг 3 ). Также в строке 22 мы получаем размер этого массива переменных из командной строки, т.е. мы запускаем этот пример с 1 миллионом записей в операции массовой вставки следующим образом:

1
java OraBulk 1000000

В строке 26 мы определяем структурный дескриптор Oracle, который сопоставляется с пользовательским типом, который мы создали ранее в нашей базе данных Oracle, « t_type » ( см. Листинг 2 ).

Далее в строках 29-31 мы заполняем массив записей, которые мы готовим для массовой вставки. То, как это делается в этом примере, немного надумано, например, дата присоединения сотрудника — это просто время, когда этот элемент повторяется в цикле, но этого будет достаточно для наших целей, несмотря на его умозаключение.

В строках 35–36 мы определяем дескриптор массива Oracle, который сопоставляется с пользовательским типом « tb_t_type » ( см. Листинг 3 ), и tb_t_type экземпляр массива Oracle, ссылаясь на структуру Oracle, которую мы определили в строке 23.

Со всеми необходимыми предварительными условиями, мы затем создаем подготовленный оператор Oracle в строке 39 для ссылки на хранимую процедуру, которую мы определили ранее в нашей базе данных Oracle ( см. Листинг 4 ). Затем он устанавливает массив Oracle в качестве первого параметра ( см. Строку 40 ).

Наконец, настроив все, мы выполняем подготовленное утверждение с небольшой помпой в строке 43.

После завершения основного события, анти-климатическая развязка на линиях 46-48 предназначена для обязательного принятия и закрытия для высвобождения ресурсов. Обратите внимание, что если исключение произошло во время массовой вставки, то все было бы откатано, так как автокоммит был бы отключен по умолчанию.

Резюме

На моем тесте производительности массовая вставка 1 миллиона записей в Oracle Database Express Edition 11g Release 2 с использованием этого кода заняла 12,55 секунд на моем ноутбуке Dell под управлением Windows 7 Home Premium с процессором Intel i5 с частотой 1,7 ГГц и 8 ГБ ОЗУ. Для драйвера Oracle JDBC я использовал ojdbc6.jar .

  • Вы можете скачать код и пример PL / SQL здесь на JCG