Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Oracle — użycie indeksu z parametrami opcjonalnymi

NVL sztuczka powinna działać i umożliwiać dostęp do indeksu. W rzeczywistości NVL jest generalnie najlepszym sposobem na zrobienie tego i zwykle działa lepiej niż inne warunki dotyczące CASE lub OR . Użyłem NVL wiele razy, a prosty przypadek testowy poniżej pokazuje, że może używać indeksu.

Schemat

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

Wygeneruj plan wykonania

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

select * from table(dbms_xplan.display);

Plan wykonania

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)

Ten plan jest początkowo trochę zagmatwany. Ale ma to, co najlepsze z obu światów; Operacja filtrowania pozwala Oracle na podjęcie w czasie wykonywania decyzji o użyciu pełnego skanowania tabeli, gdy zmienna wiązania ma wartość NULL (i zwracane są wszystkie wiersze) oraz indeks, gdy zmienna wiązania nie ma wartości NULL (i zwracanych jest tylko kilka wierszy).

To wszystko oznacza, że ​​prawdopodobnie dzieje się coś dziwnego w twoim konkretnym przypadku. Może być konieczne opublikowanie w pełni odtwarzalnego przypadku testowego, abyśmy mogli dowiedzieć się, dlaczego indeks nie jest używany.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Samouczek dotyczący formularzy i raportów Oracle 9i, Oracle 10g i Oracle 11g Developer Suite

  2. Zablokuj bazę danych Oracle przed uruchomieniem skryptów usuwania/ładowania danych

  3. (Oracle/SQL) Scal wszystkie typy danych w jedną kolumnę

  4. Nie rozumiem sortowania? (MySQL, RDBMS, zestawy znaków)

  5. Jak ustawić region strefy czasowej dla połączenia JDBC i uniknąć nieznalezionego regionu strefy czasowej SqlException?