El NVL
el truco debería funcionar y permitir el acceso al índice. De hecho, NVL
es generalmente la mejor manera de hacer esto, y generalmente funciona mejor que otras condiciones que involucran CASE
o OR
. He usado el NVL
truco muchas veces y el caso de prueba simple a continuación muestra que puede usar un índice.
Esquema
create table xx_people(id_number number, a number, b number);
insert into xx_people
select level, level, level from dual connect by level <= 100000;
commit;
begin
dbms_stats.gather_table_stats(user, 'xx_people');
end;
/
create index xx_people_idx1 on xx_people(id_number, -1);
Generar Plan de Ejecución
explain plan for
select *
from xx_people
where id_number = nvl(:p_id_number, id_number);
select * from table(dbms_xplan.display);
Plan de Ejecución
Plan hash value: 3301250992
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 100K| 3808K| 106 (1)| 00:00:01 |
| 1 | VIEW | VW_ORE_67373E14 | 100K| 3808K| 106 (1)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
|* 3 | FILTER | | | | | |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| XX_PEOPLE | 1 | 15 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | XX_PEOPLE_IDX1 | 1 | | 2 (0)| 00:00:01 |
|* 6 | FILTER | | | | | |
|* 7 | TABLE ACCESS FULL | XX_PEOPLE | 100K| 1464K| 103 (1)| 00:00:01 |
----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(:P_ID_NUMBER IS NOT NULL)
5 - access("ID_NUMBER"=:P_ID_NUMBER)
6 - filter(:P_ID_NUMBER IS NULL)
7 - filter("ID_NUMBER" IS NOT NULL)
Ese plan es un poco confuso al principio. Pero tiene lo mejor de ambos mundos; la operación de filtro permite que Oracle decida en tiempo de ejecución usar un escaneo completo de la tabla cuando la variable de vinculación es nula (y se devuelven todas las filas), y un índice cuando la variable de vinculación no es nula (y solo se devuelven unas pocas filas).
Todo esto significa que probablemente esté sucediendo algo extraño en su caso específico. Es posible que deba publicar un caso de prueba completamente reproducible para que descubramos por qué no se usa un índice.