2016-03-14 5 views
0

У нас есть процесс, который слишком долго работал, поэтому я просмотрел некоторую оптимизацию и обнаружил, что он написан довольно плохо или, по крайней мере, я думал.INSERT от SELECT против курсора в Oracle

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

Select key1, key2, key2 from a [email protected]_host_dblink; 

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

insert into localtable(col1, col2, col3 ... col15) 
select col1, col2, col3 ... col15 FROM [email protected]; 

Этот процесс не пошел хорошо - он висел в течение 30 минут, поэтому администратор базы данных убил его. Я не знаю, как это мнение написано на удаленном хосте, все, что я знаю, это то, что он, похоже, довольно подвержен налогообложению в этой системе.

Итак, вопрос в том, имеет ли вставка в выборку некоторые неотъемлемые недостатки, когда запрашивается через dblink? Будет ли это работать лучше, если бы я сначала запросил все столбцы в курсор, а затем выполнил вставки по одному на нашем конце?

ответ

1

Массовых операции через dbLinks могут быть риском, в связи с различными серверами „скорость“, сетевые накладные расходами, ...

подходом может быть что-то на полпути между этими двумя способами вы только что описали, то есть работая в основном блоками записей, а не всеми записями. Вы могли бы попробовать что-то вроде следующего (псевдо-код):

DECLARE 
    /* define a cursor on your view */ 
    CURSOR curXXX IS 
     Select key1, key2, key2 from a [email protected]_host_dblink; 
    /* define structures to keep your data */ 
    TYPE tyTabKey1 IS TABLE OF key1%type 
     INDEX BY  
    TYPE tyTabKey2 IS TABLE OF key2%type 
     INDEX BY PLS_INTEGER;;  
    TYPE tyTabKey3 IS TABLE OF key3%type 
     INDEX BY PLS_INTEGER;    
    vTabKey1 tyTabKey1; 
    vTabKey2 tyTabKey2; 
    vTabKey3 tyTabKey3; 
    ... 
    /* define how many rows you want to process at a time */ 
    kLimit number := 5000; 
BEGIN   
    OPEN curXXX;  
    LOOP 
     /* fetch the wanted number of rows */ 
     FETCH curXXX 
      BULK COLLECT INTO SOG_SOGGETTO_ID, 
       SOG_SOGGETTO_COD, 
       SOG_DATA_INI, 
       SOG_VERSIONE 
      LIMIT kLimit; 
     /* massively insert the rows */ 
     FORALL i IN 1 .. vTabKey1.COUNT 
      insert into localtable(col1, col2, col3 ... col15) 
        VALUES (vTabKey1(i), 
           vTabKey2(i), 
           ... 
          ); 

     num := num + vTabKey1.COUNT; 
     COMMIT; 
     /* loop while there are still rows to insert */ 
     EXIT WHEN SOG_SOGGETTO_ID.COUNT < kLimit; 
    END LOOP; 

    CLOSE curXXX; 
END; 
/

В этом примере я положил COMMIT; если вы решите сделать это таким же образом, обратите внимание на ошибки обработки, учитывая, что в случае ошибки вы могли бы сделать частичную вставку.

Смежные вопросы