Skip to Main Content
  • Questions
  • PLSQL Performance Tuning for conditional logic

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Shantanu.

Asked: July 25, 2018 - 4:01 pm UTC

Last updated: July 26, 2018 - 2:31 am UTC

Version: Oracle 11G

Viewed 1000+ times

You Asked

I have written a validation parser which gets called using webservice (meaning need high performance code to be run),
I have added the Example link in Live sql
where I have added conditional clauses (for null checking several input parameters and query accordingly) to the where clause of the sql part (thinking that sql optimizer will make conditional code faster) rather than using traditional IF conditions to handle the sql clauses .

However the Code reviewer thinks , that such and\or conditional clauses reduce performance of sql query , whereas I think such clauses will reduce PLSQL performance instead , (believing SQL Optimizer can optimize these conditional clauses quite efficiently)

SELECT COUNT (*)
FROM
MTL_MANUFACTURERS WHERE ( :P_MANUFACTURER_ID IS NOT NULL AND :P_MANUFACTURER_NAME IS NULL AND
MANUFACTURER_ID = :P_MANUFACTURER_ID ) OR ( :P_MANUFACTURER_ID IS NULL AND :P_MANUFACTURER_NAME IS NOT NULL AND
MANUFACTURER_NAME = :P_MANUFACTURER_NAME ) OR ( :P_MANUFACTURER_ID IS NOT NULL AND :P_MANUFACTURER_NAME IS NOT NULL AND
MANUFACTURER_NAME = :P_MANUFACTURER_NAME AND MANUFACTURER_ID = :P_MANUFACTURER_ID );


Is there any other way to increase the performance for this query?

with LiveSQL Test Case:

and Chris said...

"It depends".

The advantage of separate statements you choose between with IF clauses is you can hand-tune each. The downside is this gets impractical as you add more optional parameters.

Having a single SQL statement is easier to manage. But the downside of having all the conditional tests in one SQL statement is the optimizer will struggle to come up with a good solution in all cases. And it'll tend towards a full table scan, no matter which indexes you create.

But there is another technique which may help.

Create single columns indexes on all your searchable columns. Then write a query which:

- Has a separate select for each column matching the corresponding parameter, returning the rowid
- Union all these rowids together
- Check that the number of times each rowid is returned matches the number of non-null parameters

Which for you would look something like:

select * from mtl_manufacturers
where  rowid in (
  select rid from (
    select rowid rid from mtl_manufacturers 
    where  manufacturer_id = p_manufacturer_id
    union all
    select rowid rid from mtl_manufacturers 
    where  manufacturer_name = p_manufacturer_name
  )
  group by rid
  having count(*) = nvl2(p_manufacturer_id,1,0) + 
                    nvl2(p_manufacturer_name,1,0)
);


For more details on this method, read this post from Oren Nakdimon who came up with this approach:

http://db-oriented.com/2018/04/14/a-single-query-with-many-filter-combinations/

Now, there's no guarantee this will be better. Ultimately, there's only one way for you to know:

TEST!

Load the table with realistic production data. And compare your different methods. See which comes out best.

Rating

  (1 rating)

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

Comments

Why not ....

Tubby, July 25, 2018 - 10:04 pm UTC

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::p11_question_id:1669972300346534908

Great technique and not overly complex and ensures the optimizer gets as specific a SQL as is possible.

Cheers,
Connor McDonald
July 26, 2018 - 2:31 am UTC

Agreed.

But notice that even that has evolved over time.

More to Explore

Administration

Need more information on Administration? Check out the Administrators guide for the Oracle Database