Очередная задачка показалась мне интересной: Oracle очень плохо работает с временными таблицами(gtt - global temporary tables) в параллели.
Вообще у gtt в параллели в 11g куча ограничений, а до этого вообще запрещены:
10.2:
Restrictions on Temporary Tables:
Parallel DML and parallel queries are not supported for temporary tables. Parallel hints are ignored. Specification of the parallel_clause returns an error.
11.1:
Restrictions on Parallel DML
11.2:
Restrictions on Parallel DML:
Parallel UPDATE, DELETE and MERGE are not supported for temporary tables.
Обновление:
Я был категорически не прав: в примере, который я привел ранее, данные gtt доступны только в одном слейве. Вообще доступность этих данных организуется каким-то хитрым способом, например, поглядите на данный пример:
«Показать код...»
drop table gtt_tab;
drop function test_parallel;
create global temporary table gtt_tab (i integer) on commit preserve rows parallel 8;
create or replace function test_parallel(p_cur sys_refcursor) return sys.ku$_objnumpairlist
pipelined
parallel_enable (partition p_cur by any)
is
l_row integer;
l_cnt integer;
l_sid integer;
begin
loop
fetch p_cur into l_row;
exit when p_cur%notfound;
select count(*) into l_cnt from gtt_tab;
l_sid := sys_context('USERENV','SID');
pipe row (SYS.ku$_ObjNumPair(l_sid,l_cnt));
end loop;
end;
/
insert into gtt_tab select level from dual connect by level<=10000
/
select
num1 sid,num2 cnt,count(*)
from
table(
test_parallel(cursor(select /*+ parallel(t,8) */ * from gtt_tab t))
) tt
group by num1,num2
/
Результат:
>> select
2 num1 sid,num2 cnt,count(*)
3 from
4 table(
5 test_parallel(cursor(select /*+ parallel(t,8) */ * from gtt_tab t))
6 ) tt
7 group by num1,num2
8 ;
SID CNT COUNT(*)
---------- ---------- ----------
4956 0 2080
2981 0 2640
336 0 2640
1328 0 2640
«Ошибочный пример с видимостью только в одном слейве:»
truncate table gtt_tab;
drop function test_parallel_pipe;
drop table j_cur purge;
drop table gtt_tab purge;
drop type t_tab_row;
drop type t_row;
create or replace type t_row is object (
i integer,
n integer);
create or replace type t_tab_row is table of t_row;
create table j_cur parallel 8 as
select level l from dual connect by level<=10000;
create global temporary table gtt_tab (i integer) on commit preserve rows parallel 8;
create or replace function test_parallel_pipe(p_cur sys_refcursor) return t_tab_row
pipelined
parallel_enable (partition p_cur by any)
is
v_row integer;
v integer;
begin
loop
fetch p_cur into v_row;
exit when p_cur%notfound;
for rec in (select count(*) v from gtt_tab) loop
pipe row (t_row(v_row,rec.v));
end loop;
end loop;
end;
/
insert into gtt_tab values(1);
commit;
select
*
from
table(
test_parallel_pipe(
cursor(
select /*+ parallel(t,8) */
t.l
from j_cur t
,(select 1 ignore from gtt_tab) t_ignore
)
)
) tt;
Comments
Отправить комментарий