whether to use implicit or explicit cursors in PL/SQL. This paper provides a simple
benchmark that can help determine whether implicit or explicit cursors are the ...
About the Author Geoff Ingram (mailto:
[email protected]) is a UK-based ex-Oracle product developer who has worked as an independent Oracle consultant since leaving Oracle Corporation in the mid-nineties. He is the creator of a free Oracle performance tuning tool DbCool downloadable from http://www.dbcool.com and the author of a book published by John Wiley and Sons Inc in September 2002, covering Oracle performance and availability features in Oracle8i and Oracle9i (including Release 2): High-Performance Oracle: Proven Methods for Achieving Optimum Performance and Availability ISBN: 0-471-22436-7 http://www.wiley.com/cda/product/0,,0471224367,00.html
Implicit versus Explicit Cursors in PL/SQL © Geoff Ingram, Proton Technology Ltd 2002. No part of this document may be reproduced for any purpose without the express written permission of Proton Technology Limited.
A subject that has caused considerable debate within the Oracle community in the past is the choice of whether to use implicit or explicit cursors in PL/SQL. This paper provides a simple benchmark that can help determine whether implicit or explicit cursors are the best choice for best performance. It's assumed that you have basic familiarity with the Oracle statistics provided in the V$SESSTAT table. These statistics measure Oracle resources used by SQL statements, and are extremely useful when you need to quantify why one approach leads to faster performance than another, because differences in the statistics can provide the key. Any primer on Oracle performance tuning can provide more details. DbCool (http://www.dbcool.com) is a free Oracle performance tuning tool that can display changes in all session statistics after each SQL statement. In order to measure the performance characteristics of implicit and explicit cursors, consider a SELECT statement that returns a single-row result set. There are two ways to perform it, as shown in Table 1.
Table 1 Explicit versus Implicit Cursor Example Implicit Cursor declare l_name varchar2(30);
Explicit Cursor declare l_name varchar2(30);
begin
cursor c1 (p_id number) is select object_name from objects_list where object_id = p_id; begin
select object_name into l_name from objects_list where object_id = 20;
open c1(20); fetch c1 into l_name; close c1; end;
end;
There is an important semantic difference between the two cursors. For the implicit cursor, Oracle returns the complete result set, which may contain more than one row. If it contains more than one row, the query raises an exception because PL/SQL expects a single row result set. For the explicit cursor, rows are returned one at a time. In this case, it's up to the programmer to stop fetching after the required number of rows is returned. In the example, the programmer has chosen to perform only one fetch. A programmer can choose to stop after the first row is fetched for cases where the column used in the predicate is known to identify a single row. This is the case if the column identifies a primary key. If the query in question requires a full table scan, the explicit cursor can be faster because the implicit cursor needs to scan the whole table, whereas the programmer can choose to stop processing after the first row is returned using an explicit cursor. However, that's not the whole story when deciding to use explicit cursors instead of implicit cursors. It's clear that more code is required in the explicit case to open, fetch, and close the cursor. This means that Oracle needs to do more work to manage the cursor in the explicit case, which typically requires more CPU. The cost of the SQL executed by the cursor needs to be compared to the cost of cursor management to decide which is best. The following example sets out a test that shows when explicit cursors can be faster than implicit, and vice versa. The test data consists of a sample of 1,000 rows in DBA_OBJECTS and has an index on the table: create table cursor_test pctfree 1 pctused 99 as select rownum r,o.* from dba_objects o where rownum