Если объем данных слишком велик для обработки как единое целое, l oop укажите в датах разграничения:
SELECT * FROM DB_A
WHERE date_column >= DATE_FROM and date_column < DATE_TO
Обратите внимание, что для производительности (т.е. также для потребления памяти) не важно только количество строк результата, но способ обработки данных .
Старайтесь избегать курсора l oop на данных большого объема. Предпочтительным способом обработки является не строка за строкой , а ориентированная на набор , т.е.
INSERT .... SELECT .... FROM DB_A WHERE ...
Вы можете получить прибыль, если исходная таблица DB_A
будет секционировано в соответствующем столбце даты (date_column
в запросе выше). Запрос выберет только те разделы с ограниченными датами.
Вы можете получить прибыль (при использовании подхода SQL) от параллельного DML , чтобы повысить производительность.
Пример
Предположим, что таблица DB_A
содержит данные за 30 дней в столбце date_column
, и вы хотите обрабатывать данные в 5-дневных пакетах .
У вас будет 6 пакетов, как показано в запросе ниже.
Запрос выбирает отдельные усеченные дни из таблицы в первую очередь, а затем вычисляет batch_idx
с использованием ROW_NUMBER
и делением на 5 с помощью trunc
. Наконец, вычисляются граничные даты для batch_idx
.
with batch1 as
(select distinct trunc(date_column) start_date from db_a),
batch2 as (
select start_date,
trunc((row_number() over (order by start_date)-1) / 5) as batch_idx
from batch1)
select batch_idx, min(START_DATE) START_DATE, max(START_DATE)+1 END_DATE from batch2
group by batch_idx
order by 1
;
BATCH_IDX START_DATE END_DATE
---------- ------------------- -------------------
0 01.05.2020 00:00:00 06.05.2020 00:00:00
1 06.05.2020 00:00:00 11.05.2020 00:00:00
2 11.05.2020 00:00:00 16.05.2020 00:00:00
3 16.05.2020 00:00:00 21.05.2020 00:00:00
4 21.05.2020 00:00:00 26.05.2020 00:00:00
5 26.05.2020 00:00:00 31.05.2020 00:00:00
Тот же самый запрос, который вы можете использовать в курсоре L OOP для обработки данных, как показано ниже.
Обратите внимание, что START_DATE
является включительным, но END_DATE
является исключительным.
BEGIN
FOR cur in (
with batch1 as
(select distinct trunc(date_column) start_date from db_a),
batch2 as (
select start_date,
trunc((row_number() over (order by start_date)-1) / 5) as batch_idx
from batch1)
select batch_idx, min(START_DATE) START_DATE, max(START_DATE)+1 END_DATE from batch2
group by batch_idx
order by 1)
LOOP
dbms_output.put_line('Processing dates from '||to_char(cur.START_DATE,'dd.mm.yyyy') || ' to ' || to_char(cur.END_DATE,'dd.mm.yyyy'));
insert into DB_TARGET(date_column,....)
select date_column,.... from DB_A
where date_column >= cur.START_DATE and date_column < cur.END_DATE;
commit;
END LOOP;
END;
/
l oop будет выполняться шесть раз с ожидаемыми диапазонами дат:
Processing dates from 01.05.2020 to 06.05.2020
Processing dates from 06.05.2020 to 11.05.2020
Processing dates from 11.05.2020 to 16.05.2020
Processing dates from 16.05.2020 to 21.05.2020
Processing dates from 21.05.2020 to 26.05.2020
Processing dates from 26.05.2020 to 31.05.2020