NVL
lừa phải hoạt động và cho phép truy cập chỉ mục. Trên thực tế, NVL
nói chung là cách tốt nhất để làm điều này và thường hoạt động tốt hơn các điều kiện khác liên quan đến CASE
hoặc OR
. Tôi đã sử dụng NVL
lừa nhiều lần và trường hợp kiểm tra đơn giản bên dưới cho thấy rằng nó có thể sử dụng một chỉ mục.
Lược đồ
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);
Tạo kế hoạch thực thi
explain plan for
select *
from xx_people
where id_number = nvl(:p_id_number, id_number);
select * from table(dbms_xplan.display);
Kế hoạch thực hiện
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)
Kế hoạch đó lúc đầu hơi khó hiểu. Nhưng nó có điều tốt nhất của cả hai thế giới; hoạt động bộ lọc cho phép Oracle quyết định tại thời điểm chạy để sử dụng quét toàn bộ bảng khi biến liên kết là null (và tất cả các hàng được trả về) và một chỉ mục khi biến liên kết không phải là null (và chỉ một vài hàng được trả về).
Tất cả điều này có nghĩa là có thể có điều gì đó kỳ lạ xảy ra trong trường hợp cụ thể của bạn. Bạn có thể cần phải đăng một trường hợp thử nghiệm có thể tái tạo đầy đủ để chúng tôi tìm ra lý do tại sao một chỉ mục không được sử dụng.