более быстрый способ перемещения больших объемов данных в oracle во внешнюю базу данных - PullRequest
1 голос
/ 18 августа 2011

У меня есть Java-программа, которая сравнивает и перемещает данные из локальной базы данных Oracle во внешнюю базу данных MS SQL, размещенную онлайн-поставщиком.

В настоящее время программа подключается к базе данных MS SQL, выполняя SELECT * FROM myTABLE и помещая результаты в двумерный массив.Затем в Oracle создается временная таблица, и данные вставляются во временную таблицу с помощью цикла for:

for (int ii = 0; ii < arr.length(); ii++){
    query = "insert into myTable_temp values "+values_from_array;
    stmt.executeQuery();
} 

Используется оператор MINUS для поиска различий:

query = "select * from ora_table minus select * from myTable_temp";
rs = stmt.executeQuery();

и результат затем вставляется обратно в таблицу MS SQL с использованием метода insert_into_mssql ():

while (rs.next()){
    query = "insert into myTable values "+ values_from_rs
    insert_into_mssql(query);
}

Это прекрасно работает, за исключением того, что в используемой мной таблице содержится 220 000 строк.Таким образом, загрузка массива занимает много времени, вставляется в временную таблицу, выполняется оператор минус, а затем вставляется все обратно в таблицу mssql.

Есть ли более эффективный способ сделать это?или способ сделать это быстрее?(dblink или любое прямое соединение не работает из-за ограничений безопасности)

Ответы [ 5 ]

3 голосов
/ 18 августа 2011

Да, какую версию MS SQL Server вы используете?В зависимости от этого вы можете посмотреть SSIS или другое программное обеспечение DTS .Это позволяет очень быстро делать то, что вы хотите.

2 голосов
/ 18 августа 2011

Я думаю, что это хорошая идея - создать dblink .

1 голос
/ 18 августа 2011

Может быть, это может вам помочь.

Новый метод Statement для addBatch () позволяет объединять несколько операторов обновления в единое целое и выполнять их одновременно. Вызовите addBatch () после создания оператора и перед выполнением:

con.setAutoCommit(false); // If some fail, we want to rollback the rest
Statement stmt = con.createStatement(  );

stmt.addBatch(
"INSERT INTO CUSTOMERS VALUES (1, "J Smith", "617 555-1323");
stmt.addBatch(
"INSERT INTO CUSTOMERS VALUES (2, "A Smith", "617 555-1132");
stmt.addBatch(
"INSERT INTO CUSTOMERS VALUES (3, "C Smith", "617 555-1238");
stmt.addBatch(
"INSERT INTO CUSTOMERS VALUES (4, "K Smith", "617 555-7823");

int[] upCounts = stmt.executeBatch(  );
con.commit(  );

Обратите внимание, что мы отключаем автоматическую фиксацию транзакции перед созданием пакета.

0 голосов
/ 19 августа 2011

Принимая во внимание технологические ограничения (без dblinks и т. Д.), Вы можете попытаться снизить транспортные издержки. Это можно сделать, поддерживая состояние синхронизации и передавая только обновленные строки.

Если я правильно понимаю, вам нужно только перенести обновленные и новые строки из базы данных Oracle в MS SQL. В очень общем варианте вам нужно добавить 2 столбца в oracle_table, который содержит состояние репликации:

last_update_time - поддерживается триггером при вставке или обновлении для каждой строки. Триггер установить значение столбца на текущую дату и время при каждом изменении строки и для новой строки.

last_sync_time - поддерживается триггером при вставке и изменяется приложением синхронизации.

Для новой строки last_update_time := sysdate и last_sync_time := last_update_time - 1.

В каждом oracle_table обновлении строки last_update_time обновляется текущая дата и время.

На каждом сеансе синхронизации выполняется следующая последовательность:

  1. Выберите все строки из oracle_table, где last_sync_time < last_update_time и вставьте их в некоторую буферную таблицу на сервере Oracle:

    begin
      execute immediate 'truncate table buffer_table';
    
      insert into buffer_table(...)
      select * from oracle_table where last_sync_time < last_update_time;
    
    end;
    
  2. Перенести все строки из buffer_table на сервер MS SQL и обновить myTable соответственно.

  3. Время обновления всех синхронизированных строк до нового значения:

    update 
      oracle_table o_table
    set 
      last_sync_time = ( select buf_table.last_update_time 
                         from buffer_table buf_table
                         where buf_table.Primary_Key = o_table.Primary_Key
                       )
    where
      o_table.Primary_Key in (select Primary_Key from buffer_table)
    

Обратите внимание, что синхронизированные строки могут быть изменены во время процесса синхронизации, и нам нужно значение метки времени от buffer_table при обновлении last_sync_time.

P.S. Я предположил, что база данных на стороне MS SQL доступна только для чтения. Двустороннюю синхронизацию можно выполнить по тому же принципу с небольшими улучшениями алгоритма.

0 голосов
/ 18 августа 2011

Возможно, я бы начал с того, что не загружал его в массив и просто использовал технику, которая используется при написании. Можно также посмотреть на распараллеливание вставок.

Если бы я делал это с нуля, я перенес бы все данные Oracle на SQL Server и сделал бы там все (скопировать таблицу из Oracle, найти различия и вставить в SQL Server, удалить таблицу, скопированную из Oracle) вместо того, чтобы принести все данные SQL Server в Oracle, дамп только новые записи и перенести их в SQL Server и вставить их.

В SQL Server также есть довольно хороший инструмент ETL - службы интеграции SQL Server, но я не добился большого успеха в использовании его с другими вещами, кроме источников и назначений данных SQL Server.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...