Skip to Main Content

Oracle Database Discussions

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

Why OR condition is used as table filter predicate rather than index filter predicate?

user-3lsyfJun 3 2023

INFO:

select * from emp where deptno between :startt and :endd and (:emp_name is null or ename = :emp_name);

  • The index columns are (deptno, ename).
  • Both columns are nullable.

When i see a execution plan for the query above, the condition “(:emp_name is null or ename = :emp_name)” is used as table filter predicate rather than index filter predicate. I want to know the reason for it:

SQL_ID  87cbukvjc2n2f, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ * from emp where 1 = 1 and deptno 
between :startt and :endd     and (:emp_name is null or ename = 
:emp_name)
 
Plan hash value: 514704104
 
------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name    | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |         |      1 |        |       |     2 (100)|          |      1 |00:00:00.01 |       2 |
|*  1 |  FILTER                              |         |      1 |        |       |            |          |      1 |00:00:00.01 |       2 |
|*  2 |   TABLE ACCESS BY INDEX ROWID BATCHED| EMP     |      1 |      1 |    38 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       2 |
|*  3 |    INDEX RANGE SCAN                  | EMP_X01 |      1 |     11 |       |     1   (0)| 00:00:01 |     11 |00:00:00.01 |       1 |
------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(TO_NUMBER(:ENDD)>=TO_NUMBER(:STARTT))
   2 - filter((:EMP_NAME IS NULL OR "ENAME"=:EMP_NAME))
   3 - access("DEPTNO">=TO_NUMBER(:STARTT) AND "DEPTNO"<=TO_NUMBER(:ENDD))

I thought that the condition can be used as index filter predicate, because for the leaf blocks scanned by condition between :startt and :endd(with index access predicate), the range can be filtered with the condition (:emp_name is null or ename = :emp_name) by checking the :emp_name and ename values while using index only.

But for the check the condition (:emp_name is null or ename = :emp_name), why the table access is needed?

Thank you.

This post has been answered by Jonathan Lewis on Jun 7 2023
Jump to Answer

Comments

Post Details

Added on Jun 3 2023
16 comments
996 views