Выделение памяти под массив для bulk select

Yuriy Romanenko
Дата: 30.05.2006 14:52:15
Делаем выборку в массив из таблицы простым селектом

type t_CDR is table of tic32.cdr%rowtype;
  r_CDR t_CDR;
BEGIN
select * bulk collect into r_CDR from tic32.cdr where cdr_id between 10606618813 аnd 10606618813+2000000;               
END;

При этом размер PGA процесса раздувается до более 2Гб. Средний размер строки таблицы (согласно данных статистики в user_tables) 117 байт. Умножив на 2 млн. выбраных строк получается грубо 250Мб.

Подскажите, на что могут расходоваться еще ~1800Мб ?
andrey_anonymous
Дата: 30.05.2006 14:58:27
Yuriy Romanenko
Делаем выборку в массив из таблицы простым селектом
type t_CDR is table of tic32.cdr%rowtype;
  r_CDR t_CDR;
BEGIN
select * bulk collect into r_CDR from tic32.cdr where cdr_id between 10606618813 аnd 10606618813+2000000;               
END;
При этом размер PGA процесса раздувается до более 2Гб. Средний размер строки таблицы (согласно данных статистики в user_tables) 117 байт. Умножив на 2 млн. выбраных строк получается грубо 250Мб.
Подскажите, на что могут расходоваться еще ~1800Мб ?

А Вы еще попробуйте
declare
  l_tab dbms_sql.number_table;
begin
  l_tab(1) := 1;
  for i in 1..2000000 loop
    l_tab(i+1) := i;
    l_tab.delete(i);
  end loop;
end;
:)


Лучше объявить курсор и делать
fetch my_cur bulk collect into ... LIMIT 1000;
mcureenab
Дата: 30.05.2006 15:40:16
Yuriy Romanenko
Подскажите, на что могут расходоваться еще ~1800Мб ?


Это накладные расходы на метаданные коллекции r_CDR, тип которой относится к объектным типам. Используй PL/SQL таблицу структур rowtype она значительно меньше весит.

type t_CDR is table of tic32.cdr%rowtype index by binary_integer;

Ещё меньше весит набор таблиц встроенных типов. По таблице на колонку выборки.
Yuriy Romanenko
Дата: 30.05.2006 15:56:24
andrey_anonymous
А Вы еще попробуйте
declare
  l_tab dbms_sql.number_table;
begin
  l_tab(1) := 1;
  for i in 1..2000000 loop
    l_tab(i+1) := i;
    l_tab.delete(i);
  end loop;
end;
:)


Попробовал :-)
122Мб. Получается на каждый элемент 61 байт. Попробовал 4 млн. - 244Мб, что опять тех же 61 байт на запись.

Если написать
for i in 1000001..5000000 loop
(тоесть опять же 4 млн.), то тех же 61 байт на запись.

Вопрос остался: чего ж там так много служебного? :-)
andrey_anonymous
Дата: 30.05.2006 15:58:21
Yuriy Romanenko
Попробовал :-)
122Мб. Получается на каждый элемент 61 байт. Попробовал 4 млн. - 244Мб, что опять тех же 61 байт на запись.

Плохо считаете, Юрий :)
По завершении теста в массиве находится единственный элемент
Yuriy Romanenko
Дата: 30.05.2006 16:10:28
mcureenab

Это накладные расходы на метаданные коллекции r_CDR, тип которой относится к объектным типам. Используй PL/SQL таблицу структур rowtype она значительно меньше весит.

type t_CDR is table of tic32.cdr%rowtype index by binary_integer;

Я и использую PL/SQL таблицу структур rowtype (или ошибаюсь?):
type t_CDR is table of tic32.cdr%rowtype;
r_CDR t_CDR;
Yuriy Romanenko
Дата: 30.05.2006 16:13:34
andrey_anonymous
Плохо считаете, Юрий :)
По завершении теста в массиве находится единственный элемент

Это все оракл :)

Находится то один, а место выделено под все.
andrey_anonymous
Дата: 30.05.2006 17:41:25
Yuriy Romanenko
andrey_anonymous
Плохо считаете, Юрий :)
По завершении теста в массиве находится единственный элемент

Это все оракл :)
Находится то один, а место выделено под все.

Тогда попробуйте так:
declare
  l_tab dbms_sql.number_table;
begin
  l_tab(1) := 1;
  for i in 1..2000000 loop
    l_tab.delete(i);
    l_tab(i+1) := i;
  end loop;
end;
mcureenab
Дата: 30.05.2006 18:48:42
Yuriy Romanenko

Я и использую PL/SQL таблицу структур rowtype (или ошибаюсь?):
type t_CDR is table of tic32.cdr%rowtype;
r_CDR t_CDR;



Ошибаешься. PL/SQL таблица это:

type t_CDR is table of tic32.cdr%rowtype index by binary_integer;

а у тебя коллекция. Разница в три слова : "index by binary_integer", а эффект потрясающий. У этих типов даже методы отличаются.
mcureenab
Дата: 30.05.2006 18:56:21
andrey_anonymous
...Тогда попробуйте так:...


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