索引優化原則及Oracle中索引總結


索引建立原則

  • 確定針對該表的操作是大量的查詢操作還是大量的增刪改操作。
  • 嘗試建立索引來幫助特定的查詢。檢查自己的sql語句,為那些頻繁在where子句中出現的字段建立索引。
  • where語句中不得不對查詢列采用函數查詢,如upper函數,最好建立相應函數索引;
  • 在SQL語句中經常進行GROUP BY、ORDER BY的字段上建立索引
  • 用於聯接的列(主健/外健)上建立索引;
  • 在經常存取的多個列上建立復合索引,但要注意復合索引的建立順序要按照使用的頻度來確定;
  • 嘗試建立復合索引來進一步提高系統性能。修改復合索引將消耗更長時間,同時,復合索引也占磁盤空間。
  • 對於小型的表,建立索引可能會影響性能
  • 在不同值較少的字段上不必要建立索引,如性別字段;
  • 應該避免對具有較少值的字段進行索引。???
  • 避免選擇大型數據類型的列作為索引。
  • 缺省情況下建立的是非簇集索引,但在以下情況下最好考慮簇集索引,如:含有有限數目(不是很少)唯一的列;進行大范圍的查詢;
  • 充分的利用索引可以減少表掃描I/0的次數,有效的避免對整表的搜索。當然合理的索引要建立在對各種查詢的分析和預測中
  • 避免在有大量並發DML運算的表中使用Bitmap索引;
  • 經常被更新,或者一個表雖然很大,但是如果多數查詢返回結果都超過表中總行數的4%,那么一般認為也是不宜建立索引的。
  • 經常查詢的記錄數目少於表中所有記錄總數的5%時就應當創建索引
  • 存儲索引的表空間最好單獨設定
  • 隨着數據的變化,索引的效率會下降,因此應定期重建索引

 

oracle位圖索引  B-樹索引

B-樹索引在Oracle中是一個通用的索引,在創建索引時它就是默認的索引類型。最多可以包括32列。

    創建語句:create index indexName on tableName(columnName);

    特點: 

        1.索引不存儲null值。更准確的說,單列索引不存儲null值,復合索引不存儲全為Null的值。索引不能存儲Null,所以對這列采用is null條件時,因為索引上根本沒Null值,不能利用到索引,只能全表掃描。

        2.不適合鍵值較少的列。與數據塊有關。

        3.前導模糊查詢不能利用索引(like '%XX'或者like '%XX%')。這樣會導致全表掃描。

位圖索引Oracle為每個唯一鍵創建一個位圖,然后把與鍵值所關聯的ROWID保存為位圖。最多可以包括30列。

    創建語句:create bitmap index indexName on tableName(columnName);

    特點:

        1.相對於B*Tree索引,占用的空間非常小,創建和使用非常快。位圖索引由於只存儲鍵值的起止Rowid和位圖,占用的空間非常少。

        2.不適合鍵值較多的列。

        3.不適合update、insert、delete頻繁的列。

        4.可以存儲null值。B*Tree索引由於不記錄空值,當基於is null的查詢時,會使用全表掃描,而對位圖索引列進行is null查詢時,則可以使用索引。

        5.當select count(XX) 時,可以直接訪問索引中一個位圖就快速得出統計數據。

        6.當根據鍵值做and,or或 in(x,y,..)查詢時,直接用索引的位圖進行或運算,快速得出結果行數據。

    位圖索引有很多限制:

        基於規則的優化器不會考慮位圖索引

        當執行ATLER TABLE語句,並修改包含有位圖索引的列時,會使位圖索引失效

        位圖索引在索引塊中儲存了索引鍵的值;然而,他們並不能用戶任何類型的完整性檢查

        位圖索引不能被申明為唯一索引

 

索引不會被命中的情況

1、查詢謂詞沒有使用索引的主要邊界,可能會導致不走索引。

    查詢:SELECT * FROM T WHERE Y=XXX;

    假如T表上有一個包含Y值的組合索引,但是優化器會認為需要一行行的掃描會更有效,這個時候,優化器可能會選擇TABLE ACCESS FULL,

    查詢換成:SELECT Y FROM T WHERE Y = XXX,優化器會直接去索引中找到Y的值,因為從B樹中就可以找相應的值。 

2、如果在B樹索引中有一個空值的時候,優化器可能不會走索引。

    查詢:那么查詢諸如SELECT COUNT(*) FROM T 

    有兩種方式可以讓索引有效,一種是SELECT COUNT(*) FROM T WHERE XXX IS NOT NULL或者是不能為空。 

3、在索引字段上使用函數,導致不會走索引。

    查詢:SELECT * FROM T WHERE FUN(Y) = XXX。

    如果在T表上有一個索引Y時,索引也不會被用到,因為你要查詢的列中所有的行都需要被計算一遍,

    可以在這個表上建立一個基於函數的索引,比如CREATE INDEX IDXFUNT ON T(FUN(Y));這種方式,等於Oracle會建立一個存儲所有函數計算結果的值,再進行查詢的時候就不需要進行計算了。 

4、索引不適用於隱式轉換的情況。

    查詢:SELECT * FROM T WHERE Y = 5 

    在Y上面有一個索引,但是Y列是VARCHAR2的,那么Oracle會將上面的5進行一個隱式的轉換成SELECT * FROM T WHERE TO_NUMBER(Y) = 5,這個時候也是有可能用不到索引的。 

5、如果表只有幾個數據塊大小,而且可以被Oracle一次性抓取,那么就沒有使用索引的必要了,因為抓取索引還需要去根據rowid從數據塊中獲取相應的元素值,因此在表特別小的情況下,索引沒有用到是情理當中的事情。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM