1. 程式人生 > >Oracle資料庫索引培訓——201609

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會優先轉換數值型別到字元型別

4.2 ORACLE的HINT詳解

hints是oracle提供的一種機制,用來告訴優化器按照我們的告訴它的方式生成執行計劃。我們可以用hints來實現.

4.3 Oracle查詢計劃例子(有興趣的自行閱讀)

執行計劃分析才是sql優化的關鍵,可以根據實際執行計劃來檢查是否按照預想的來執行。 備註:合理的使用Hint來引導執行計劃