sql >> Databasteknik >  >> RDS >> Oracle

Oracle - Indexanvändning med valfria parametrar

NVL trick borde fungera och tillåta indexåtkomst. Faktum är att NVL är i allmänhet det bästa sättet att göra detta, och fungerar vanligtvis bättre än andra förhållanden som involverar CASE eller OR . Jag har använt NVL trick många gånger och det enkla testfallet nedan visar att det kan använda ett index.

Schema

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

Generera exekveringsplan

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

select * from table(dbms_xplan.display);

Utförandeplan

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 planen är lite förvirrande till en början. Men den har det bästa av två världar; filteroperationen tillåter Oracle att vid körning besluta att använda en fullständig tabellsökning när bindningsvariabeln är null (och alla rader returneras), och ett index när bindningsvariabeln inte är null (och endast ett fåtal rader returneras).

Allt detta betyder att det förmodligen är något konstigt som händer i ditt specifika fall. Du kan behöva lägga upp ett helt reproducerbart testfall för att vi ska ta reda på varför ett index inte används.




  1. hur man jämför två mysql-tabeller i php

  2. PHP/MySql Välj kommentarer grupperade med svar

  3. tolka användarskrivna fulltextsökningsfrågor till WHERE-satsen i MySQL med PHP

  4. Postgres UPSERT återanvänd kolumnvärden från INSERT vid UPDATE