Oracle資料庫索引培訓——201609
1. 資料庫發展概要介紹
觀點:關係資料庫在子應用中還是會繼續存在,隨著資料大爆炸的不斷升級,關係資料庫將會更方便的遷移到大資料平臺。大資料引導消費、大資料支撐模型、大資料輔助決策 將 會是一個商業常態。
2. Oracle優化器(RBO與CBO)
Oracle的優化器有兩種,基於規則的優化器(RBO)和基於代價的優化器(CBO)。
在8i之前,Oracle使用的是RBO(Rule Based Optimizer,基於規則的優化器),他的執行非常簡單,就是在優化器裡面嵌入15中規則,執行SQL語句符合哪種規則,就按照規則定製出相應的SQL執行計劃。由於他是一種過時呆板的優化器,在10g以後的版本中已經被踢出掉了。從8i開始,Oracle引入了CBO(Cost Based Optimizer,基於代價的優化器),他的思路是讓Oracle獲取所有的執行計劃的相關資訊,通過這些資訊做計算分析,最後得出一個代價最小的執行計劃作為最終的執行計劃.
3.1 索引按儲存方法分類,可以分為2類:B*樹索引和點陣圖索引。
1) 二元高度(binary height)
2) ORACLE B樹索引概念的理解
3) 點陣圖索引概念的理解
http://blog.csdn.net/lxqluo/article/details/52462829
3.2 索引按功能和索引物件分還有以下型別
1) 唯一索引意味著不會有兩行記錄相同的索引鍵值。唯一索引表中的記錄沒有RowID,不能再對其建立其他索引。在oracle10g中,要建立唯一索引,必須在表中設定主關鍵字,建立了唯一索引的表只按照該唯一索引結構排序。
2) 非唯一索引不對索引列的值進行唯一性限制。
3) 分割槽索引是指索引可以分散地存在於多個不同的表空間中,其優點是可以提高資料查詢的效率。
4) 未排序索引也稱為正向索引。Oracle10g資料庫中的行是按升序排序的,建立索引時不必指定對其排序而使用預設的順序。
5) 逆序索引也稱反向索引。該索引同樣保持列按順序排列,但是顛倒已索引的每列的位元組。
6) 基於函式的索引是指索引中的一列或者多列是一個函式或者表示式,索引根據函式或表示式計算索引列的值。可以將基於函式的索引建立建立成點陣圖索引。
另外,按照索引所包含的列數可以把索引分為單列索引和複合索引。索引列只有一列的索引為單列索引,對多列同時索引稱為複合索引。
4.ORACLE效能優化之SQL語句優化
4.1 Oracle優化的基本原則
以下是從上面的博文摘取出來規則(包括規則的序號): (1)選擇最有效率的表名順序(只在基於規則的優化器中有效):ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表(基礎表 driving table)將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。如果有3個以上的表連線查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表.
(2)WHERE子句中的連線順序.:
ORACLE採用自下而上的順序解析WHERE子句,根據這個原理,表之間的連線必須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾.
(3)SELECT子句中避免使用 ‘ * ‘:
ORACLE在解析的過程中, 會將'*' 依次轉換成所有的列名, 這個工作是通過查詢資料字典完成的, 這意味著將耗費更多的時間
(11)用Where子句替換HAVING子句:
(14)使用表的別名(Alias):
當在SQL語句中連線多個表時, 請使用表的別名並把別名字首於每個Column上.這樣一來,就可以減少解析的時間並減少那些由Column歧義引起的語法錯誤.
(15)用EXISTS替代IN、用NOT EXISTS替代NOT IN:
在許多基於基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率. 在子查詢中,NOT IN子句將執行一個內部的排序和合並. 無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷). 為了避免使用NOT IN ,我們可以把它改寫成外連線(Outer Joins)或NOT EXISTS.
例子:
(高效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
(21)避免在索引列上使用NOT 通常,
我們要避免在索引列上使用NOT, NOT會產生在和在索引列上使用函式相同的影響. 當ORACLE”遇到”NOT,他就會停止使用索引轉而執行全表掃描.
(22)避免在索引列上使用計算.
WHERE子句中,如果索引列是函式的一部分.優化器將不使用索引而使用全表掃描.
舉例:
低效:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;
(26)避免在索引列上使用IS NULL和IS NOT NULL
避免在索引中使用任何可以為空的列,ORACLE將無法使用該索引.對於單列索引,如果列包含空值,索引中將不存在此記錄. 對於複合索引,如果每個列都為空,索引中同樣不存在此記錄. 如果至少有一個列不為空,則記錄存在於索引中.舉例: 如果唯一性索引建立在表的A列和B列上, 並且表中存在一條記錄的A,B值為(123,null) , ORACLE將不接受下一條具有相同A,B值(123,null)的記錄(插入). 然而如果所有的索引列都為空,ORACLE將認為整個鍵值為空而空不等於空. 因此你可以插入1000 條具有相同鍵值的記錄,當然它們都是空! 因為空值不存在於索引列中,所以WHERE子句中對索引列進行空值比較將使ORACLE停用該索引.
低效: (索引失效)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
高效: (索引有效)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;
(27)總是使用索引的第一個列:
如果索引是建立在多個列上, 只有在它的第一個列(leading column)被where子句引用時,優化器才會選擇使用該索引. 這也是一條簡單而重要的規則,當僅引用索引的第二個列時,優化器使用了全表掃描而忽略了索引
(30)避免改變索引列的型別.:
當比較不同資料型別的資料時, ORACLE自動對列進行簡單的型別轉換.
假設 EMPNO是一個數值型別的索引列.
SELECT … FROM EMP WHERE EMPNO = ‘123'
實際上,經過ORACLE型別轉換, 語句轉化為:
SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123')
幸運的是,型別轉換沒有發生在索引列上,索引的用途沒有被改變.
現在,假設EMP_TYPE是一個字元型別的索引列.
SELECT … FROM EMP WHERE EMP_TYPE = 123
這個語句被ORACLE轉換為:
SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123
因為內部發生的型別轉換, 這個索引將不會被用到! 為了避免ORACLE對你的SQL進行隱式的型別轉換, 最好把型別轉換用顯式表現出來. 注意當字元和數值比較時, ORACLE會優先轉換數值型別到字元型別