Oracle
 sql >> база данни >  >> RDS >> Oracle

Oracle - Използване на индекс с незадължителни параметри

NVL трикът трябва да работи и да позволи достъп до индекса. Всъщност NVL обикновено е най-добрият начин да направите това и обикновено работи по-добре от други условия, включващи CASE или OR . Използвал съм NVL трик много пъти и простият тестов случай по-долу показва, че може да използва индекс.

Схема

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

Генериране на план за изпълнение

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

select * from table(dbms_xplan.display);

План за изпълнение

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)

Този план е малко объркващ в началото. Но има най-доброто от двата свята; филтърната операция позволява на Oracle да реши по време на изпълнение да използва пълно сканиране на таблица, когато свързващата променлива е нулева (и се връщат всички редове) и индекс, когато свързващата променлива не е нулева (и се връщат само няколко реда).

Всичко това означава, че вероятно във вашия конкретен случай се случва нещо странно. Може да се наложи да публикувате напълно възпроизводим тестов случай, за да разберем защо даден индекс не се използва.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. как да обединя повече от две колони в plsql developer?

  2. Издаден SQL Developer 4.0

  3. Как да извадите 2 дати в Oracle, за да получите резултата за час и минута

  4. Oracle 10g Time Zone Confusion

  5. Извършване на групови актуализации със съхранени процедури MyBatis и Oracle