Почему поведение конвейерной функции при выводе результата не отличается от нормальной табличной функции?
Создал конвейерную функцию, и другую, не конвейерную функцию. Но обе функции при вызове в запросе отображают результат только после полного выполнения.
Почему конвейерная функция не возвращает каждую запись, как только данные для неё становятся доступными?
Вот код функций:
create or replace type tfrow as object (cnt number, description varchar2(50));
/
create or replace type tftab as table of tfrow;
/
create or replace function gettab(cnt int, sec int) return tftab as
t tftab := tftab();
begin
for i in 1..cnt loop
dbms_session.sleep(sec);
t.extend;
t(t.last) := tfrow(i,'row #'||i);
end loop;
return t;
end;
/
create or replace function gettabp(cnt int, sec int) return tftab pipelined as
begin
for i in 1..cnt loop
dbms_session.sleep(sec);
pipe row(tfrow(i,'piped row #'||i));
end loop;
return;
end;
/
Вот так их вызываю:
--TF call
select * from table (gettab (10, 1));
--pipelined TF call
select * from table (gettabp(10, 1));
Поведение обоих не отличается, каждый запрос через 10 сек. выводит 10 записей.
Свободный перевод вопроса Oracle Pipelined function working like normal function от участника @gunaseelan thirumal
Ответы (1 шт):
Конвейерная функция работает корректно, но с целью оптимизации производительности размер выборки в клиенте извлекает N строк, прежде чем вернет вообще что-либо. N зависит от клиента и устанавливается в каждом клиенте по разному.
Чтобы сразу увидеть в выводе возвращаемые отдельные строки, надо отключить (или уменьшить) размер выборки.
В SQL*Plus это достигается командой set arraysize 1 (по умолчанию установлено 15). На самом деле, будет выводится не одна, а две строки за раз, по причине того, что SQL*Plus выбирает дополнительно одну строку в т.н. prefetch, который нельзя отключить. Чтобы увидеть, когда действительно записи стали доступны, можно создать простую функцию, которая в запросе вернёт штамп времени для каждой записи результата:
create or replace function getts return varchar2 is
begin
return to_char (systimestamp, 'mi:ss.ff3');
end;
/
Результат конвейерной функции будет выводится пакетами по 2 записи за раз:
SQL> set arrays 1
SQL> select t.*, getts ts from table (gettabp(9, 1)) t
/
CNT DESCRIPTION TS
---------- ------------ ------------
1 piped row #1 44:23.018
2 piped row #2 44:24.072
3 piped row #3 44:25.096
[...]
8 piped row #8 44:30.216
9 piped row #9 44:31.240
9 rows selected.
Результат нормальной табличной функции будет доступрен через ~9 сек. и все 9 записей будут выведены за раз:
SQL> select t.*, getts ts from table (gettab (9, 1)) t
CNT DESCRIPTION TS
---------- ------------ ------------
1 row #1 49:40.681
2 row #2 49:40.688
3 row #3 49:40.688
[...]
8 row #8 49:40.718
9 row #9 49:40.718
9 rows selected.