我创建了一个名为 Z7 的索引,我想在这样的 SELECT 语句中使用它:
SELECT * FROM Employees WITH (INDEX(Z7)) WHERE First_Name NOT LIKE ('J%');
但它向我展示了这个错误:
ORA-00933: SQL 命令未正确结束
与LIKE
可以通过索引范围扫描解决的谓词相反,Oracle 中没有索引访问路径可以实现NOT LIKE
需要在LIKE 值之前和之后执行两次范围扫描的索引访问路径。
让我们在这个设置中用一个表来说明它,该表只有一行满足您的不喜欢谓词。
create table Employees as
select 'J'||rownum as First_Name, lpad('x',1000,'y') pad from dual connect by level <= 10000
union all
select 'Xname', 'zzzzz' from dual;
create index Z7 on Employees (First_Name);
查询
SELECT * FROM Employees WHERE First_Name NOT LIKE ('J%');
按预期执行 FULL TABLE SCAN
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 37 | 37259 | 398 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMPLOYEES | 37 | 37259 | 398 (1)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FIRST_NAME" NOT LIKE 'J%')
您可能会提示Oracle 使用索引如下(注意您的语法FROM Employees WITH (INDEX(Z7)) WHERE
错误并导致您的错误!)
SELECT /*+ index(Employees Z7) */ * FROM Employees WHERE First_Name NOT LIKE ('J%');
这确实会导致索引使用,但不是您可能想要的。
如果您检查执行计划,您将看到INDEX FULL SCAN
,这意味着,Oracle 会遍历从to 开始的完整索引,过滤索引中作为谓词的全部内容(请参阅下面的计划中的 ),并针对选定的键访问表.A
Z
not like
FILTER
因此,通常您不会对大索引的这个计划感到满意,因为它需要比全表扫描更长的时间。
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9433 | 9276K| 2912 (1)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| EMPLOYEES | 9433 | 9276K| 2912 (1)| 00:00:01 |
|* 2 | INDEX FULL SCAN | Z7 | 9433 | | 25 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("FIRST_NAME" NOT LIKE 'J%')
见这里如何产生执行计划用于查询
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句