I have a performance problem with an Oracle select statement that I use in a cursor. In the statement one of the terms in the SELECT
clause is expensive to evaluate (it's a PL/SQL procedure call, which accesses the database quite heavily). The WHERE
clause and ORDER BY
clauses are straightforward, however.
I expected that Oracle would first perform the WHERE
clause to identify the set of records that match the query, then perform the ORDER BY
clause to order them, and finally evaluate each of the terms in the SELECT
clause. As I'm using this statement in a cursor from which I then pull results, I expected that the expensive evaluation of the SELECT
term would only be performed as needed, when each result was requested from the cursor.
However, I've found that this is not the sequence that Oracle uses. Instead it appears to evaluate the terms in the SELECT
clause for each record that matches the WHERE clause before performing the sort. Due to this, the procedure that is expensive to call is called for every result result in the result set before any results are returned from the cursor.
I want to be able to get the first results out of the cursor as quickly as possible. Can anyone tell me how to persuade Oracle not to evaluate the procedure call in the SELECT statement until after the sort has been performed?
This is all probably easier to describe in example code:
Given a table example
with columns a
, b
, c
and d
, I have a statement like:
select a, b, expensive_procedure(c)
from example
where <the_where_clause>
order by d;
On executing this, expensive_procedure()
is called for every record that matches the WHERE
clause, even if I open the statement as a cursor and only pull one result from it.
I've tried restructuring the statement as:
select a, b, expensive_procedure(c)
from example, (select example2.rowid, ROWNUM
from example example2
where <the_where_clause>
order by d)
where example.rowid = example2.rowid;
Where the presence of ROWNUM
in the inner SELECT
statement forces Oracle to evaluate it first. This restructuring has the desired performance benefit. Unfortunately it doesn't always respect the ordering that is required.
Just to be clear, I know that I won't be improving the time it takes to return the entire result set. I'm looking to improve the time taken to return the first few results from the statement. I want the time taken to be progressive as I iterate over the results from the cursor, not all of it to elapse before the first result is returned.
Can any Oracle gurus tell me how I can persuade Oracle to stop executing the PL/SQL until it is necessary?