Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Копирование списков порциями / 25 сообщений из 29, страница 1 из 2
08.11.2018, 16:13
    #39730020
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Добрый день! В таблице SCHEMA_NAME.TABLE_NAME есть 10000 значений. Нужно их порциями по 100 штук копировать в список, производить какие-то действия с ним и замерять время для каждых 100 значений. Мне представляется такой вариант:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
DECLARE
  l_VPUSubList   SYS.ODCINUMBERLIST;
  l_TotalVPUList SYS.ODCINUMBERLIST;
  indSub   INTEGER;   indTotal INTEGER;
  start_time TIMESTAMP WITH TIME ZONE;
  end_time TIMESTAMP WITH TIME ZONE;
  exec_length INTERVAL DAY TO SECOND;
BEGIN
  select VPU_NUM 
  BULK COLLECT INTO l_TotalVPUList
  from SCHEMA_NAME.TABLE_NAME
  
  indSub := 1; indTotal := 1;
  WHILE indTotal <= l_TotalVPUList.LAST
  LOOP
    --dbms_output.put_line (ind);
    l_VPUSubList(indSub) := l_TotalVPUList(indTotal);
    indSub := indSub + 1; indTotal := indTotal + 1;
    IF MOD (indTotal, 100) = 0 -- Каждые 100 значений
    THEN
      start_time := SYSTIMESTAMP;
      --Здесь какие-то действия с этими 100 значений
      end_time := SYSTIMESTAMP;
      exec_length := end_time - start_time;
      dbms_output.put_line('Длина в формате дни часы:минуты:секунды: '||exec_length);
    END IF;
  END LOOP;  
END;



Но при попытке запуска скрипта возниакет ошибка:ORA-06531: Ссылка на неинициализированный набор
ORA-06512: на line 18

Как избавиться от неё или как более эффективно написать скрипт?
...
Рейтинг: 0 / 0
08.11.2018, 16:19
    #39730023
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
ultrasonic7Как избавиться от неё или как более эффективно написать скрипт?
1. bulk collect имеет кляузу LIMIT.
2. Изложите цикл в виде
Код: plsql
1.
for i in 1.. l_TotalVPUList.count loop


Это избавит от необходимости отдельно обрабатывать случай пустой коллекции, с которым Вы столкнулись.
...
Рейтинг: 0 / 0
08.11.2018, 16:20
    #39730025
Вячеслав Любомудров
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Я думаю, что тут столкнулись с
ultrasonic7
Код: plsql
1.
2.
...
    l_VPUSubList(indSub) := l_TotalVPUList(indTotal);
...
Рейтинг: 0 / 0
08.11.2018, 16:21
    #39730027
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
ultrasonic7Как избавиться от неёпоставить return после begin, потому как очевидного решения, инициализировать переменную, будет недостаточно, чтобы избежать последующих ошибок.
ultrasonic7как более эффективно написать скрипт?курсор + limit 100
...
Рейтинг: 0 / 0
08.11.2018, 16:23
    #39730028
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
andrey_anonymousслучай пустой коллекции, с которым Вы столкнулись.
Слишком по диагонали смотрел, сорри.
Вот это:
Код: plsql
1.
l_VPUSubList   SYS.ODCINUMBERLIST;


надо инициализировать и расширять руками.
Лучше объявите ассоциативный массив.
...
Рейтинг: 0 / 0
08.11.2018, 16:24
    #39730029
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
ultrasonic7Как избавиться

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
DECLARE
  l_VPUSubList   SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();
  l_TotalVPUList SYS.ODCINUMBERLIST;
  indSub   INTEGER;   indTotal INTEGER;
  start_time TIMESTAMP WITH TIME ZONE;
  end_time TIMESTAMP WITH TIME ZONE;
  exec_length INTERVAL DAY TO SECOND;
BEGIN
  select VPU_NUM 
  BULK COLLECT INTO l_TotalVPUList
  from SCHEMA_NAME.TABLE_NAME
  
  indSub := 1; indTotal := 1;
  l_VPUSubList.extend(l_TotalVPUList.LAST);
  WHILE indTotal <= l_TotalVPUList.LAST
  LOOP
    --dbms_output.put_line (ind);
    l_VPUSubList(indSub) := l_TotalVPUList(indTotal);
    indSub := indSub + 1; indTotal := indTotal + 1;
    IF MOD (indTotal, 100) = 0 -- Каждые 100 значений
    THEN
      start_time := SYSTIMESTAMP;
      --Здесь какие-то действия с этими 100 значений
      end_time := SYSTIMESTAMP;
      exec_length := end_time - start_time;
      dbms_output.put_line('Длина в формате дни часы:минуты:секунды: '||exec_length);
    END IF;
  END LOOP;  
END;



SY
...
Рейтинг: 0 / 0
09.11.2018, 10:28
    #39730333
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Суть в том, что l_VPUSubList должен быть именно типа SYS.ODCINUMBERLIST и содержать 100 элементов.
То, что список надо расширить
Код: plsql
1.
l_VPUSubList.extend(l_TotalVPUList.LAST);


понятно. Но l_TotalVPUList.LAST содержит 10000 значений, а мне нужно копировать в l_VPUSubList порциями по 100 и для каждой итерации цикла вызывать процедуру, у которой входной параметр SYS.ODCINUMBERLIST и условия запуска требуют, чтобы в нём было 100 значений.
Не проще ли будет один раз расширить l_VPUSubList на 100 элементов?
Код: plsql
1.
l_VPUSubList.extend(100);
...
Рейтинг: 0 / 0
09.11.2018, 10:37
    #39730344
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Нет, проверил, такой вариант не подходит. В этом случае индекс выходит за пределы счетчика массива. Нужно каждый раз копировать перезаписывать прежние 100 значений в l_VPUSubList следующими 100 значениями из l_TotalVPUList.
...
Рейтинг: 0 / 0
09.11.2018, 10:38
    #39730346
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
ultrasonic7прощеandrey_anonymousкляузу LIMIT
...
Рейтинг: 0 / 0
09.11.2018, 10:40
    #39730347
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Хотел написать не "копировать", а "перезаписывать"
...
Рейтинг: 0 / 0
09.11.2018, 11:01
    #39730372
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
ultrasonic7Нет, проверил, такой вариант не подходит. В этом случае индекс выходит за пределы счетчика массива. Нужно каждый раз копировать перезаписывать прежние 100 значений в l_VPUSubList следующими 100 значениями из l_TotalVPUList.

каждые 100 записей indSub надо сбрасывать indSub:=1;

ps
к-во записей всегда кратно 100?

.....
stax
...
Рейтинг: 0 / 0
09.11.2018, 12:06
    #39730444
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Staxк-во записей всегда кратно 100?

Да.
...
Рейтинг: 0 / 0
09.11.2018, 12:36
    #39730493
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
ultrasonic7Staxк-во записей всегда кратно 100?

Да.

есть мнение что Вы обрабатываете не 100, а 99 записей (indTotal := indTotal + 1; IF MOD (indTotal, 100) = 0 -- Каждые 100 значений)

зы
повторно, в IF счетчик надо сбрасывать

.....
stax
...
Рейтинг: 0 / 0
09.11.2018, 14:38
    #39730597
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Staxповторно, в IF счетчик надо сбрасывать
.....
stax
Да, надо это учесть.
...
Рейтинг: 0 / 0
09.11.2018, 15:07
    #39730639
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Утомительная какая-то тема.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
DECLARE
  cursor c_data is -- тут запрос к данным
    select ROWNUM  VPU_NUM 
      from dual connect by level < 1000;

  type t_numtbl is table of c_data%rowtype index by pls_integer;
  l_VPUList t_numtbl;

  c_batch_size constant integer := 100; -- размер пачки
  start_time TIMESTAMP(6);
  exec_length INTERVAL DAY TO SECOND;

BEGIN
  open c_data;
  loop
    fetch c_data bulk collect into l_VPUList limit c_batch_size;
    start_time := SYSTIMESTAMP;
    for i in 1..l_VPUList.count() loop
      --Здесь какие-то действия с этими 100 значений
      null;
    end loop;
    exec_length := SYSTIMESTAMP - start_time;
    dbms_output.put_line('Обработано '||l_VPUList.count||' элементов; Продолжительность обработки: '||exec_length);
  exit when l_VPUList.count < c_batch_size;
  end loop;  
END;

...
Рейтинг: 0 / 0
09.11.2018, 15:16
    #39730648
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
andrey_anonymous,

Код: plsql
1.
2.
    for i in 1..l_VPUList.count() loop
    end loop;


не нужен

....
stax
...
Рейтинг: 0 / 0
09.11.2018, 15:19
    #39730651
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Staxandrey_anonymous,

Код: plsql
1.
2.
    for i in 1..l_VPUList.count() loop
    end loop;


не нужен
Там "какие-то действия", а ТС цикл по коллекции формирует как Бог на душу положит - вылетит опять за границы, напишет нам "случилась ошибка" - гадай потом...
...
Рейтинг: 0 / 0
09.11.2018, 15:23
    #39730656
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
andrey_anonymousТам "какие-то действия",


автор а мне нужно копировать в l_VPUSubList порциями по 100 и для каждой итерации цикла вызывать процедуру, у которой входной параметр SYS.ODCINUMBERLIST и условия запуска требуют, чтобы в нём было 100 значений.

.....
stax
...
Рейтинг: 0 / 0
09.11.2018, 15:33
    #39730678
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Staxandrey_anonymousТам "какие-то действия",

авторвходной параметр SYS.ODCINUMBERLIST и условия запуска требуют, чтобы в нём было 100 значений.

Просмотрел.
Надо тогда тип коллекции обратно поменять :)
...
Рейтинг: 0 / 0
12.11.2018, 09:55
    #39731554
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
В результате сделал так. Фетч происходит прямо в SYS.ODCINUMBERLIST, а внутренний цикл получается ненужным.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
DECLARE
  cursor c_data is -- тут запрос к данным
    select VPU_NUM 
    from SCHEMA_NAME.TABLE_NAME;

  l_VPUList SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();

  c_batch_size constant integer := 100; -- размер пачки
  start_time TIMESTAMP WITH TIME ZONE;
  total_start_time TIMESTAMP WITH TIME ZONE;
  exec_length INTERVAL DAY TO SECOND;
  total_exec_length INTERVAL DAY TO SECOND;

BEGIN
  l_VPUList.extend(c_batch_size);
  total_start_time := SYSTIMESTAMP;
  open c_data;
  loop
    fetch c_data bulk collect into l_VPUList limit c_batch_size;
    start_time := SYSTIMESTAMP;
    SCHEMA_NAME.PACKAGE_NAME.PROC_NAME(param_in => l_VPUList);
    exec_length := SYSTIMESTAMP - start_time;
    dbms_output.put_line('Обработано '||l_VPUList.count||' элементов; Продолжительность обработки - часы:минуты:секунды: '||exec_length);
  exit when l_VPUList.count < c_batch_size;
  end loop;
  total_exec_length := SYSTIMESTAMP - total_start_time;
  dbms_output.put_line('Общая продолжительность обработки - часы:минуты:секунды: '||total_exec_length);  
END;
...
Рейтинг: 0 / 0
12.11.2018, 10:00
    #39731557
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Спасибо всем ответившим.
...
Рейтинг: 0 / 0
12.11.2018, 13:23
    #39731706
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
ultrasonic7,

SCHEMA_NAME.PACKAGE_NAME.PROC_NAME(param_in => l_VPUList); может отработать на пустой набор

.....
stax
...
Рейтинг: 0 / 0
13.11.2018, 15:00
    #39732466
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Stax,
Да, есть такое. После обработки последних 100 элементов из 10000:
Обработано 100 элементов; Продолжительность обработки - часы:минуты:секунды: +00 00:00:00.210193
обрабатывается 0 элементов:
Обработано 0 элементов; Продолжительность обработки - часы:минуты:секунды: +00 00:00:00.007318
Какую проверку добавить, чтобы список из 0 элементов не обрабатывался?
Так не помогает:
Код: plsql
1.
2.
IF l_VPUList IS NOT NULL THEN
      SOME_PROC(iDocIDs => l_VPUList);


так тоже:
Код: plsql
1.
2.
IF l_VPUList.COUNT > 0 THEN
      SOME_PROC(iDocIDs => l_VPUList);
...
Рейтинг: 0 / 0
13.11.2018, 15:05
    #39732469
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
так тоже не помогает
Код: plsql
1.
IF c_data%ROWCOUNT > 0 THEN
...
Рейтинг: 0 / 0
13.11.2018, 15:17
    #39732476
ultrasonic7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Копирование списков порциями
Сам себе ответил. Надо было сделать так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
DECLARE
  cursor c_data is
    select VPU_NUM 
    from SCHEMA_NAME.TABLE_NAME;

  l_VPUList SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();

  c_batch_size constant integer := 100; -- размер пачки
  start_time TIMESTAMP WITH TIME ZONE;
  total_start_time TIMESTAMP WITH TIME ZONE;
  exec_length INTERVAL DAY TO SECOND;
  total_exec_length INTERVAL DAY TO SECOND;

BEGIN
  l_VPUList.extend(c_batch_size);
  total_start_time := SYSTIMESTAMP;
  open c_data;
  loop
    fetch c_data bulk collect into l_VPUList limit c_batch_size;
    IF c_data%FOUND THEN
      start_time := SYSTIMESTAMP;
      SCHEMA_NAME.PACKAGE_NAME.PROC_NAME(param_in => l_VPUList);
      COMMIT;
      exec_length := SYSTIMESTAMP - start_time;
      dbms_output.put_line('Обработано '||l_VPUList.count||' элементов; Продолжительность обработки - часы:минуты:секунды: '||exec_length);
    END IF;
  exit when l_VPUList.count < c_batch_size;
  end loop;
  total_exec_length := SYSTIMESTAMP - total_start_time;
  close c_data;
  dbms_output.put_line('Общая продолжительность обработки - часы:минуты:секунды: '||total_exec_length);  
END;
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Копирование списков порциями / 25 сообщений из 29, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]