Вставка Oracle с прямой загрузкой из 54 061 487 записей - PullRequest
4 голосов
/ 26 октября 2011

У меня есть прямая загрузка вставки 54 061 487 записей. Я ищу скорость. Мне не нужен откат вообще.

Все задействованные таблицы установлены на NOLOGGING.

Вот один из способов сделать это

EXECUTE IMMEDIATE 'TRUNCATE TABLE meRegionsNow';
...

INSERT /*+ APPEND */ INTO meRegionsNow(
   carrierId     ,
   region        ,
   zip           ,
   side          ,
   subPlanTypeId ,
   monthIn       )
   SELECT
      r.carrierId     as carrierId     ,
      r.region        as region        ,
      r.zip           as zip           ,
      r.side          as side          ,
      r.subPlanTypeId as subPlanTypeId ,
      t.monthIn       as monthIn
   FROM
      meTimeline t
         INNER JOIN region r
         ON t.monthIn >= r.effective AND
            t.monthIn <= r.expiry;

План выполнения для этого, как и ожидалось (используя право индексы для ускорения объединения):

 Statement Id=5336   Type=  
 Cost=2.64022111505165E-308  TimeStamp=25-10-11::15::35:08  

   (1)  SELECT STATEMENT  ALL_ROWS   
 Est. Rows: 5,667  Cost: 483  
   (5)  TABLE TABLE ACCESS BY INDEX ROWID SCHEMA.REGION  [Analyzed]   
   (5)   Blocks: 2,826 Est. Rows: 944 of 377,779  Cost: 80   
 Tablespace: USERS  
       (4)  NESTED LOOPS   
            Est. Rows: 5,667  Cost: 483  
           (2)  INDEX INDEX FULL SCAN SCHEMA.METL$MONTHIN  [Analyzed]   
                Est. Rows: 6  Cost: 1  
           (3)  INDEX INDEX RANGE SCAN SCHEMA.RGN$MULTI3  [Analyzed]   
                Est. Rows: 944  Cost: 72  

Вот еще один способ сделать это:

EXECUTE IMMEDIATE 'TRUNCATE TABLE meRegionsNow';
...

DECLARE
   CURSOR meTimeline_cur IS
      SELECT monthIn
      FROM meTimeline
      ORDER BY monthIn;
BEGIN
   FOR meTimeline_rec IN meTimeline_cur LOOP
      /* Cross regions with timeline */
      INSERT /*+ APPEND */ INTO meRegionsNow(
         carrierId     ,
         region        ,
         zip           ,
         side          ,
         subPlanTypeId ,
         monthIn       )
         SELECT
            r.carrierId            as carrierId     ,
            r.region               as region        ,
            r.zip                  as zip           ,
            r.side                 as side          ,
            r.subPlanTypeId        as subPlanTypeId ,
            meTimeline_rec.monthIn as monthIn
         FROM region r
         WHERE
            meTimeline_rec.monthIn >= r.effective AND
            meTimeline_rec.monthIn <= r.expiry;
      COMMIT;
   END LOOP;
END;

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

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

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

Ответы [ 3 ]

4 голосов
/ 26 октября 2011

Первый подход, вероятно, будет более быстрым, поскольку в нем меньше переключений контекста между механизмом PL / SQL и механизмом SQL. Вы можете легко узнать, попробовав оба метода.

2 голосов
/ 26 октября 2011

Вы пытались распараллелить нагрузку, используя параллельный совет? (может оказаться, что вам нужно удалить / сделать недействительными ограничения и индексы во время загрузки, а затем снова включить их после загрузки)

INSERT /*+ APPEND PARALLEL*/ INTO meRegionsNow( ..... 
    SELECT /*+ PARALLEL*/ .....

Есть много предварительных условий для параллельной и прямой загрузки для работы ....

см .: http://download.oracle.com/docs/cd/E11882_01/server.112/e17118/statements_9014.htm#SQLRF01604 см: http://download.oracle.com/docs/cd/E11882_01/server.112/e16541/parallel003.htm#VLDBG1455

0 голосов
/ 26 октября 2011

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

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

...