Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Shibaji.

Asked: March 24, 2017 - 3:33 am UTC

Last updated: March 26, 2017 - 10:10 am UTC

Version: 11G

Viewed 1000+ times

You Asked

Hi,

Could you please let me know that how to judge that what should be our limit while using a bulk collect for fetching cursors.I have read in various blogs that using bulk collect is not always a good option as it can degrade performance in few cases.

Kindly let me know about the same in details....


Thanks in Advance...

Regards
Shibaji

and Connor said...

There is no hard and fast rule.

*Generally* bulk collect is going to be faster than row-by-row fetching, but with a diminishing level of returns as the limit gets higher. For example

SQL> create table t
  2  as select d.* from dba_objects d,
  3    ( select 1 from dual connect by level <= 10 );

Table created.

SQL> declare
  2    type tlist is table of t%rowtype
  3      index by pls_integer;
  4    r tlist;
  5    s timestamp;
  6    limit_size int := 5;
  7    cursor c is select * from t;
  8  begin
  9    for i in 1 .. 8 loop
 10      s := localtimestamp;
 11      open c;
 12      loop
 13        fetch c bulk collect into r limit limit_size;
 14        exit when c%notfound;
 15      end loop;
 16      close c;
 17      dbms_output.put_line('Limit='||limit_size||',time='||(localtimestamp-s));
 18      limit_size :=limit_size * 2;
 19    end loop;
 20  end;
 21  /
Limit=5,time=+000000000 00:00:02.866000000
Limit=10,time=+000000000 00:00:02.239000000
Limit=20,time=+000000000 00:00:02.007000000
Limit=40,time=+000000000 00:00:01.855000000
Limit=80,time=+000000000 00:00:01.734000000
Limit=160,time=+000000000 00:00:01.747000000
Limit=320,time=+000000000 00:00:01.758000000
Limit=640,time=+000000000 00:00:01.762000000

PL/SQL procedure successfully completed.




So on my machine, above 80 I'm not seeing much benefit. There are some boundary cases that *might* come into play. For example, I might get lucky and find 10 rows at the very "top" of a table, and the 11th row is much further through in a full table scan...So in that particular case, a limit of 10 would appear faster than a limit of 20, for the first pass....But they are generally not worth considering custom code to handle.

My general approach is:

- if I *know* its one row (eg primary key lookup), I use select-into
- if I *know* its a small finite list (eg "list of countries") I'll just select-bulk-collect
- otherwise I'll fetch with a 100 fetch size.



Is this answer out of date? If it is, please let us know via a Comment

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library