Каков максимальный предел массового сбора во вложенной таблице (я использую его для 10 миллионов записей) - PullRequest
0 голосов
/ 02 мая 2018

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

begin
 type bandtvarray is table of BANDWISETVCOVERAGE%rowtype;
            Band_arr bandtvarray;

FOR j IN 1 .. 24 LOOP
  --
  DELETE from BANDWISETVCOVERAGE 
  WHERE trunc(CREATEDDATE)<trunc(sysdate-60) 
       AND ROWNUM<1000000  
      returning  BANDWISETVCOVERAGEID_PK 
      BULK COLLECT into Band_arr;
   --
  forall i in 1 .. Band_arr.count
        insert into ARC_BANDWISETVCOVERAGE  
        values Band_arr(i);
        Band_arr.DELETE();
   commit;
    --
END LOOP;

1 Ответ

0 голосов
/ 01 июня 2018

Краткий ответ: на самом деле ограничений нет (кроме доступной системной памяти), но я думаю, что вы задаете неправильный вопрос. Правильный вопрос: какой хороший размер использовать для массовых переплетов? Точного числа действительно нет, но есть несколько вещей, которые следует учитывать:

  • Вы используете массовые привязки для уменьшения переключения контекста (от механизма обработки PL / SQL, выполняющего вашу программу, до механизма базы данных, вставляющего строки и обратно)
  • Чем больше ваша коллекция, тем больше памяти занимает ваша программа
  • Со временем вы сделаете коллекцию настолько большой, что ваша программа будет работать не медленно из-за переключения контекста, а по какой-то другой причине (ЦП, доступная память, конфликт дисков и т. Д.)

Мое личное правило - от 100 до 250 строк - это хороший размер. Вы можете проверить это сами и увидеть, что, поскольку коллекция получает очень большую производительность, на самом деле это НАДЕЖДА. Вы хотите выбрать число, которое работает хорошо и использует наименьшее количество памяти: мой тест ниже показывает, что даже 50 - это достаточно хорошее значение.

DROP TABLE t;
DROP TABLE v;

CREATE TABLE t AS
SELECT * FROM all_objects
CROSS JOIN (SELECT LEVEL FROM dual CONNECT BY LEVEL <= 10);

SELECT COUNT(*) FROM t;
-- 770260

CREATE TABLE v AS SELECT * FROM t WHERE 0 = 1;

DECLARE
  TYPE t_tab IS TABLE OF t%ROWTYPE;
  x_tab t_tab;

  CURSOR c IS
    SELECT *
      FROM t;

  c_bulk_size INTEGER := 50000;
  v_start     TIMESTAMP(9) := current_timestamp;
BEGIN
  OPEN c;

  LOOP
    FETCH c BULK COLLECT
      INTO x_tab LIMIT c_bulk_size;

    IF x_tab.count > 0 THEN
      FORALL i IN x_tab.first .. x_tab.last
        INSERT INTO v
        VALUES x_tab
          (i);
    END IF;

    EXIT WHEN x_tab.count < c_bulk_size;
  END LOOP;

  dbms_output.put_line((current_timestamp - v_start) || ' size ' ||
                       c_bulk_size);

  CLOSE c;

  ROLLBACK;
END;
/
-- +000000000 00:00:11.696873000 size 50
-- +000000000 00:00:12.692300000 size 50
-- +000000000 00:00:11.634849000 size 50

-- +000000000 00:00:12.770239000 size 100
-- +000000000 00:00:11.268332000 size 100
-- +000000000 00:00:11.793120000 size 100

-- +000000000 00:00:11.400098000 size 250
-- +000000000 00:00:10.625674000 size 250
-- +000000000 00:00:11.783102000 size 250

-- +000000000 00:00:09.490830000 size 500
-- +000000000 00:00:10.411275000 size 500
-- +000000000 00:00:11.713433000 size 500

-- +000000000 00:00:09.140556000 size 1000
-- +000000000 00:00:12.459841000 size 1000
-- +000000000 00:00:09.132134000 size 1000

-- +000000000 00:00:10.188990000 size 10000
-- +000000000 00:00:09.758166000 size 10000
-- +000000000 00:00:10.685548000 size 10000

-- +000000000 00:00:19.255858000 size 50000
-- +000000000 00:00:20.929404000 size 50000
-- +000000000 00:00:24.243393000 size 50000

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

...