sql >> Database teknologi >  >> RDS >> Oracle

Oracle - Indeksbrug med valgfri parametre

NVL trick burde virke og tillade indeksadgang. Faktisk NVL er generelt den bedste måde at gøre dette på, og fungerer normalt bedre end andre forhold, der involverer CASE eller OR . Jeg har brugt NVL trick mange gange, og den simple testcase nedenfor viser, at den kan bruge et indeks.

Skema

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);

Generer eksekveringsplan

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

select * from table(dbms_xplan.display);

Udførelsesplan

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)

Den plan er lidt forvirrende i starten. Men den har det bedste fra begge verdener; filteroperationen tillader Oracle at beslutte på kørselstidspunktet at bruge en fuld tabelscanning, når bind-variablen er null (og alle rækker returneres), og et indeks, når bind-variablen ikke er null (og kun få rækker returneres).

Det betyder alt sammen, at der sandsynligvis sker noget underligt i dit specifikke tilfælde. Du skal muligvis sende en fuldt reproducerbar testcase, for at vi kan finde ud af, hvorfor et indeks ikke bruges.




  1. ORA-01830:billede i datoformat slutter før konvertering af hele inputstrengen / Vælg sum hvor datoforespørgsel

  2. Optimal størrelse til databasepartitioner

  3. Får du ugens start- og slutdato? i sql server?

  4. MySQL - GROUP BY med ORDER DESC virker ikke