用索引提高效率
索引是表的一個概念部分
除了那些LONG或LONG RAW數據類型
雖然使用索引能得到查詢效率的提高
存儲
定期的重構索引是有必要的
ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
索引的操作
ORACLE對索引有兩種訪問模式
索引唯一掃描 ( INDEX UNIQUE SCAN)
大多數情況下
例如:
表LODGING有兩個索引 : 建立在LODGING列上的唯一性索引LODGING_PK和建立在MANAGER列上的非唯一性索引LODGING$MANAGER
SELECT * FROM LODGING
WHERE LODGING =
在內部
如果被檢索返回的列包括在INDEX列中
下面SQL只需要INDEX UNIQUE SCAN 操作
SELECT LODGING FROM LODGING WHERE LODGING =
索引范圍查詢(INDEX RANGE SCAN)
適用於兩種情況:
例
SELECT LODGING FROM LODGING WHERE LODGING LIKE
WHERE子句條件包括一系列值
例
SELECT LODGING FROM LODGING WHERE MANAGER =
這個SQL的執行分兩步
由於SQL返回LODGING列
WHERE子句中
SELECT LODGING FROM LODGING WHERE MANAGER LIKE
在這種情況下
基礎表的選擇
基礎表(Driving Table)是指被最先訪問的表(通常以全表掃描的方式被訪問)
如果你使用的是CBO (COST BASED OPTIMIZER)
如果你用RBO (RULE BASED OPTIMIZER)
舉例:
SELECT A
WHERE A
由於LODGING表的LODING列上有一個索引
多個平等的索引
當SQL語句的執行路徑可以使用分布在多個表上的多個索引時
在ORACLE選擇執行路徑時
當WHERE子句中索引列和常量比較才有效
如果不同表中兩個想同等級的索引將被引用
如果相同表中兩個想同等級的索引將被引用
舉例:
DEPTNO上有一個非唯一性索引
SELECT ENAME
這裡
TABLE ACCESS BY ROWID ON EMP AND
INDEX RANGE SCAN ON CAT_IDX
等式比較和范圍比較
當WHERE子句中有索引列
舉例:
DEPTNO上有一個非唯一性索引
SELECT ENAME FROM EMP WHERE DEPTNO >
這裡只有EMP_CAT索引被用到
TABLE ACCESS BY ROWID ON EMP
INDEX RANGE SCAN ON CAT_IDX
不明確的索引等級
當ORACLE無法判斷索引的等級高低差別
舉例:
DEPTNO上有一個非唯一性索引
SELECT ENAME FROM EMP WHERE DEPTNO >
這裡
TABLE ACCESS BY ROWID ON EMP
INDEX RANGE SCAN ON DEPT_IDX
我們來試一下以下這種情況:
SQL> select index_name
INDEX_NAME UNIQUENES
EMPNO UNIQUE
EMPTYPE NONUNIQUE
SQL> select * from emp where empno >=
no rows selected
Execution Plan
雖然EMPNO是唯一性索引
強制索引失效
如果兩個或以上索引具有相同的等級
舉例:
SELECT ENAME FROM EMP WHERE EMPNO =
AND DEPTNO +
AND EMP_TYPE ||
這是一種相當直接的提高查詢效率的辦法
這裡有一個例子關於何時采用這種策略
假設在EMP表的EMP_TYPE列上有一個非唯一性的索引而EMP_CLASS上沒有索引
SELECT ENAME FROM EMP WHERE EMP_TYPE =
優化器會注意到EMP_TYPE上的索引並使用它
用下面的方案就可以解決問題
SELECT ENAME FROM EMP WHERE EMP_TYPE =
避免在索引列上使用計算.
WHERE子句中
舉例:
低效
SELECT … FROM DEPT WHERE SAL *
高效:
SELECT … FROM DEPT WHERE SAL >
自動選擇索引
如果表中有兩個以上(包括兩個)索引
在這種情況下
舉例:
SELECT ENAME FROM EMP WHERE EMPNO =
AND DEPTNO =
這裡
TABLE ACCESS BY ROWID ON EMP
INDEX UNIQUE SCAN ON EMP_NO_IDX
避免在索引列上使用NOT
通常
影響
舉例:
低效: (這裡
SELECT … FROM DEPT WHERE DEPT_CODE NOT =
高效: (這裡
SELECT … FROM DEPT WHERE DEPT_CODE >
需要注意的是
NOT > to <=
NOT >= to <
NOT < to >=
NOT <= to >
SQL> select * from emp where NOT empno >
no rows selected
Execution Plan
SQL> select * from emp where empno <=
no rows selected
Execution Plan
兩者的效率完全一樣
用>=替代>
如果DEPTNO上有一個索引
高效:
SELECT * FROM EMP WHERE DEPTNO >=
低效:
SELECT * FROM EMP WHERE DEPTNO >
兩者的區別在於
From:http://tw.wingwit.com/Article/program/Oracle/201311/17710.html