2010-04-27

Pipelining

In reducing number of function calls I wrote about how to rewrite a query that is calling a function. Another approach to the issue is to alter the function. The function includes only a SQL clause. The whole result of the clause is bulk collected first and then returned. The usage of the function is in IN clause. IN predicate is satisfied if there is one equality coming out of the select. So in the best cases it is not needed to populate the whole bulk collect inside the function. Using pipelining as an alternative here.

Original bulk collect version.

SQL> create or replace type ns_typ is table of number;
2 /

Type created.

SQL> create or replace function rn(n number) return ns_typ is
2 ret ns_typ;
3 begin
4 dbms_lock.sleep(1);
5 select level bulk collect into ret from dual connect by level <= n;
6 return ret;
7 end;
8 /

Function created.

And the pipelined version of the function.

SQL> create or replace function rnpiped(n number) return ns_typ pipelined is
2 begin
3 for ret in
4 (select level l from dual connect by level <= n)
5 loop
6 dbms_lock.sleep(1/n);
7 pipe row (ret.l);
8 end loop;
9 end;
10 /



If the whole result returned from the function is needed there is no great difference in the execution times. Actually it seems to be increasing a bit.



SQL> select * from table(rn(10));

COLUMN_VALUE
------------
1
2
3
4
5
6
7
8
9
10

10 rows selected.

Elapsed: 00:00:01.00
SQL>
SQL> select * from table(rnpiped(10));

COLUMN_VALUE
------------
1
2
3
4
5
6
7
8
9
10

10 rows selected.

Elapsed: 00:00:01.07


But when used in IN predicate the results with this data are even better than in the previous post.


SQL> select * from ta a where a.n in (select * from table(rn(a.m)));

N M
---------- ----------
1 2
2 3

Elapsed: 00:00:10.00
SQL>
SQL> select * from ta a where a.n in (select * from table(rnpiped(a.m)));

N M
---------- ----------
1 2
2 3

Elapsed: 00:00:01.95


And putting both together.



SQL> with aa as (
2 select *
3 from ta a
4 ), bb as (
5 select distinct m
6 from aa
7 ), cc as (
8 select /*+materialize*/ b.m, dd.column_value n
9 from bb b, table(rn(b.m)) dd)
10 select *
11 from aa
12 where (n,m) in (select n,m from cc)
13 ;

N M
---------- ----------
1 2
2 3

Elapsed: 00:00:03.09
SQL>
SQL> with aa as (
2 select *
3 from ta a
4 ), bb as (
5 select distinct m
6 from aa
7 ), cc as (
8 select /*+materialize*/ b.m, dd.column_value n
9 from bb b, table(rnpiped(b.m)) dd)
10 select *
11 from aa
12 where (n,m) in (select n,m from cc)
13 ;

N M
---------- ----------
1 2
2 3

Elapsed: 00:00:00.68

No comments:

Post a Comment

About Me

My photo
I am Timo Raitalaakso. I have been working since 2001 at Solita Oy as a Senior Database Specialist. I have received Oracle ACE nomination. My main focus is on projects involving Oracle database. In this Rafu on db blog I write some interesting issues that evolves from my interaction with databases. Mainly Oracle.