When using a variable or constant, the plan shows access path INDEX RANGE SCAN (MIN/MAX). But with the function, slower INDEX RANGE SCAN is performed. How to achieve INDEX RANGE SCAN (MIN/MAX) when using a function?
DB version 19c.
create table t1(id number, status number);
create index t1i on t1(status, id);
insert into t1 select level+1e9, mod(level,10) from dual connect by level < 1e6;
commit;
exec dbms_stats.gather_Table_stats(ownname => null, tabname => 'T1', method_opt => 'for all columns size auto')
create or replace function f1 return number as
pragma udf;
begin
return 1;
end;
/
SQL> set autotrace traceonly explain statistic
SQL> set linesize 999
SQL> select max(id) from t1 where status = 1;
Execution Plan
----------------------------------------------------------
Plan hash value: 1124291149
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
| 2 | FIRST ROW | | 1 | 26 | 1 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN (MIN/MAX)| T1I | 1 | 26 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("STATUS"=1)
Statistics
----------------------------------------------------------
3 consistent gets
...
SQL> select max(id) from t1 where status = f1;
Execution Plan
----------------------------------------------------------
Plan hash value: 1736604837
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
|* 2 | INDEX RANGE SCAN| T1I | 1 | 26 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("STATUS"="F1"())
Statistics
----------------------------------------------------------
529 consistent gets
...
SQL> select id -- workaround
2 from (select /*+ index_desc(t1) */ id from t1 where status = f1 order by status desc, id desc)
3 where rownum=1;
Execution Plan
----------------------------------------------------------
Plan hash value: 2152446242
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 3 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | VIEW | | 1 | 13 | 3 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN DESCENDING| T1I | 1 | 10 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM=1)
3 - access("STATUS"="F1"())
Statistics
----------------------------------------------------------
3 consistent gets
...