使用索引的誤區之二:使用了 和 != 操作符,導致查詢不使用索引
使用索引的誤區之二:使用了 <> 和 != 操作符,導致查詢不使用索引
首先,請記住這個結論:
使用了<> 和!=後,就不會使用索引
例如,下面的例子使用了<>,所以查詢沒有用到索引
select empno from emp where empno <>10;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | TABLE ACCESS FULL | EMP | | | |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("EMP"."EMPNO"<>10)
Note: rule based optimization
14 rows selected
將上面的查條件“empno <>10”轉換成“empno <10 and empno>10”後,就可以使用索引了
select empno from emp where empno <10 and empno>10;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | INDEX RANGE SCAN | EMP_ID1 | | | |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("EMP"."EMPNO">10 AND "EMP"."EMPNO"<10)
Note: rule based optimization
14 rows selected
SQL>
再看下面的例子:
由於使用了前導列,所以使用了索引,後面的"!="是從索引範圍掃描的結果中篩選合適的記錄的
select empno from emp where empno <=10 and ename != @#RICH@#;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | INDEX RANGE SCAN | EMP_ID1 | | | |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("EMP"."EMPNO"<=10)
filter("EMP"."EMPNO"<=10 AND "EMP"."ENAME"<>@#RICH@#)
Note: rule based optimization
15 rows selected
再做一個試驗:
SQL> desc dept
Name Type Nullable Default Comments
------ ------------ -------- ------- --------
DEPTNO NUMBER(2) Y
DNAME VARCHAR2(14) Y
LOC VARCHAR2(13) Y
創建一個單鍵索引:
SQL> create index dept_id1 on dept(dname);
Index created
如果使用"<>",則查詢不使用索引:
select depTno from dept where dname <> @#DEVELOPER@#;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | TABLE ACCESS FULL | DEPT | | | |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DEPT"."DNAME"<>@#DEVELOPER@#)
Note: rule based optimization
14 rows selected
將條件修改爲“dname <@#DEVELOPER@# and dname>@#DEVELOPER@#”,則可以使用索引
select deptno from dept where dname <@#DEVELOPER@# and dname>@#DEVELOPER@#;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
| 1 | TABLE ACCESS BY INDEX ROWID| DEPT | | | |
|* 2 | INDEX RANGE SCAN | DEPT_ID1 | | | |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPT"."DNAME">@#DEVELOPER@# AND "DEPT"."DNAME"<@#DEVELOPER@#)
Note: rule based optimization
15 rows selected
SQL>
首先,請記住這個結論:
使用了<> 和!=後,就不會使用索引
例如,下面的例子使用了<>,所以查詢沒有用到索引
select empno from emp where empno <>10;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | TABLE ACCESS FULL | EMP | | | |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("EMP"."EMPNO"<>10)
Note: rule based optimization
14 rows selected
將上面的查條件“empno <>10”轉換成“empno <10 and empno>10”後,就可以使用索引了
select empno from emp where empno <10 and empno>10;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | INDEX RANGE SCAN | EMP_ID1 | | | |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("EMP"."EMPNO">10 AND "EMP"."EMPNO"<10)
Note: rule based optimization
14 rows selected
SQL>
再看下面的例子:
由於使用了前導列,所以使用了索引,後面的"!="是從索引範圍掃描的結果中篩選合適的記錄的
select empno from emp where empno <=10 and ename != @#RICH@#;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | INDEX RANGE SCAN | EMP_ID1 | | | |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("EMP"."EMPNO"<=10)
filter("EMP"."EMPNO"<=10 AND "EMP"."ENAME"<>@#RICH@#)
Note: rule based optimization
15 rows selected
再做一個試驗:
SQL> desc dept
Name Type Nullable Default Comments
------ ------------ -------- ------- --------
DEPTNO NUMBER(2) Y
DNAME VARCHAR2(14) Y
LOC VARCHAR2(13) Y
創建一個單鍵索引:
SQL> create index dept_id1 on dept(dname);
Index created
如果使用"<>",則查詢不使用索引:
select depTno from dept where dname <> @#DEVELOPER@#;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
|* 1 | TABLE ACCESS FULL | DEPT | | | |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DEPT"."DNAME"<>@#DEVELOPER@#)
Note: rule based optimization
14 rows selected
將條件修改爲“dname <@#DEVELOPER@# and dname>@#DEVELOPER@#”,則可以使用索引
select deptno from dept where dname <@#DEVELOPER@# and dname>@#DEVELOPER@#;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
| 1 | TABLE ACCESS BY INDEX ROWID| DEPT | | | |
|* 2 | INDEX RANGE SCAN | DEPT_ID1 | | | |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPT"."DNAME">@#DEVELOPER@# AND "DEPT"."DNAME"<@#DEVELOPER@#)
Note: rule based optimization
15 rows selected
SQL>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.