Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle - Uso de índice com parâmetros opcionais


O NVL truque deve funcionar e permitir o acesso ao índice. Na verdade, NVL geralmente é a melhor maneira de fazer isso e geralmente funciona melhor do que outras condições envolvendo CASE ou OR . Eu usei o NVL trick muitas vezes e o caso de teste simples abaixo mostra que ele pode usar um í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);

Gerar Plano de Execução

explain plan for
select *
from xx_people
where id_number = nvl(:p_id_number, id_number);

select * from table(dbms_xplan.display);

Plano de Execução

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)

Esse plano é um pouco confuso no início. Mas tem o melhor dos dois mundos; a operação de filtro permite que o Oracle decida em tempo de execução usar uma varredura completa da tabela quando a variável de ligação for nula (e todas as linhas forem retornadas) e um índice quando a variável de ligação não for nula (e apenas algumas linhas forem retornadas).

Isso tudo significa que provavelmente há algo estranho acontecendo no seu caso específico. Talvez seja necessário publicar um caso de teste totalmente reproduzível para descobrirmos por que um índice não é usado.