假设您在 Oracle 中有一个表:
CREATE TABLE person (
id NUMBER PRIMARY KEY,
given_names VARCHAR2(50),
surname VARCHAR2(50)
);
使用这些基于函数的索引:
CREATE INDEX idx_person_upper_given_names ON person (UPPER(given_names));
CREATE INDEX idx_person_upper_last_name ON person (UPPER(last_name));
现在, given_names 没有 NULL 值,但为了论证, last_name 有。如果我这样做:
SELECT * FROM person WHERE UPPER(given_names) LIKE 'P%'
解释计划告诉我它使用索引但将其更改为:
SELECT * FROM person WHERE UPPER(last_name) LIKE 'P%'
它没有。 Oracle 文档说,只有在满足多个条件时才会使用基于函数的索引,其中之一是确保没有 NULL 值,因为它们没有被索引。
我试过这些查询:
SELECT * FROM person WHERE UPPER(last_name) LIKE 'P%' AND UPPER(last_name) IS NOT NULL
和
SELECT * FROM person WHERE UPPER(last_name) LIKE 'P%' AND last_name IS NOT NULL
在后一种情况下,我什至在 last_name 上添加了一个索引,但无论我尝试什么,它都使用全表扫描。假设我无法摆脱 NULL 值,如何让这个查询使用 UPPER(last_name) 上的索引?
最佳答案
可以使用索引,但优化器可能选择不将它用于您的特定示例:
SQL> create table my_objects
2 as select object_id, object_name
3 from all_objects;
Table created.
SQL> select count(*) from my_objects;
2 /
COUNT(*)
----------
83783
SQL> alter table my_objects modify object_name null;
Table altered.
SQL> update my_objects
2 set object_name=null
3 where object_name like 'T%';
1305 rows updated.
SQL> create index my_objects_name on my_objects (lower(object_name));
Index created.
SQL> set autotrace traceonly
SQL> select * from my_objects
2 where lower(object_name) like 'emp%';
29 rows selected.
Execution Plan
----------------------------------------------------------
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 17 | 510 | 355 (1)|
| 1 | TABLE ACCESS BY INDEX ROWID| MY_OBJECTS | 17 | 510 | 355 (1)|
|* 2 | INDEX RANGE SCAN | MY_OBJECTS_NAME | 671 | | 6 (0)|
------------------------------------------------------------------------------------
您阅读的文档大概指出,就像任何其他索引一样,全空键不存储在索引中。
关于sql - 如何在 Oracle 10+ 中对包含 NULL 的列使用基于函数的索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/177240/