为什么在这个查询中使用的是INDEX RANGE SCAN,而不是INDEX FAST FULL SCAN,因为所有的值都在索引本身中,可以从那里选择而不需要参考表?
-- Создание таблицы и построение функционального индекса
create table del_nvl_ind as
select
id,
case when val < 1 then null else round(val)*12 end val
from
(
select
level id,
level * dbms_random.value val
from dual
connect by level < 1000000
);
create index del_nvl_idx_nvl on del_nvl_ind (nvl(val,0));
-- Получение плана запроса
explain plan for
select val from del_nvl_ind where nvl(val,0) = 100;
select * from table(dbms_xplan.display);
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10000 | 107K| 600 (1)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| DEL_NVL_IND | 10000 | 107K| 600 (1)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | DEL_NVL_IDX_NVL | 4000 | | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(NVL("VAL",0)=100)
还有一个问题 - 我如何更改查询以便 INDEX FAST FULL SCAN 出现在计划中?
由于以下原因,存在对表格的引用和使用 INDEX RANGE SCAN:
建立在 nvl(val,0) 上的索引没有覆盖字段 val。由于索引包含已转换的值,并且表本身包含原始值(没有通过函数转换)。将查询的 SELECT 子句中的 VAL 表达式更改为 NVL(VAL,0) 后,使用了索引,而没有引用原始数据的表。
INDEX RANGE SCAN是索引数据范围访问方式,INDEX (FAST) FULL SCAN是全数据集访问方式。并且由于查询谓词(WHERE)包含限制数据集的条件,因此完全选择没有意义,因此使用了这种特殊的访问方法(RANGE SCAN)。