Oracle執行計劃不走索引的緣由總結

Oracle數據庫操做中,爲何有時一個表的某個字段明明有索引,當觀察一些語的執行計劃確 不走索引呢?如何解決呢?本文咱們主要就介紹這部份內容,接下來就讓咱們一塊兒來了解一下。

不走索引大致有如下幾個緣由: sql

  • 你在Instance級別所用的是all_rows的方式
  • 你的表的統計信息(最可能的緣由)
  • 你的表很小,上文提到過的,Oracle的優化器認爲不值得走索引。

解決方法: 數據庫

能夠修改init.ora中的OPTIMIZER_MODE這個參數,把它改成Rule或Choose,重起數據庫。也可使用4中所提的Hint。 服務器

不走索引的其它緣由: 函數

一、創建組合索引,但查詢謂詞並未使用組合索引的第一列,此處有一個INDEX SKIP SCAN概念。 工具

二、在包含有null值的table列上創建索引,當時使用select count(*) from table時不會使用索引。 oop

三、在索引列上使用函數時不會使用索引,若是必定要使用索引只能創建函數索引。 優化

四、當被索引的列進行隱式的類型轉換時不會使用索引。如:select * from t where indexed_column = 5,而indexed_column列創建索引但類型是字符型,這時Oracle會產生隱式的類型轉換,轉換後的語句相似於select * from t where to_number(indexed_column) = 5,此時不走索引的狀況相似於case3。日期轉換也有相似問題,如: select * from t where trunc(date_col) = trunc(sysdate)其中date_col爲索引列,這樣寫不會走索引,可改寫成select * from t where date_col >= trunc(sysdate) and date_col < trunc(sysdate+1),此查詢會走索引。 spa

五、並非全部狀況使用索引都會加快查詢速度,full scan table 有時會更快,尤爲是當查詢的數據量佔整個表的比重較大時,由於full scan table採用的是多塊讀,當Oracle優化器沒有選擇使用索引時不要當即強制使用,要充分證實使用索引確實查詢更快時再使用強制索引。 操作系統

六、<> 調試

七、like’%dd’百分號在前。

關於Oracle執行計劃不走索引的緣由的相關知識的總結就介紹到這裏了,但願本次的介紹可以對您有所收穫!


Oracle數據庫不能使用索引的緣由定位

 
Oracle數據庫有時候出現 不能使用索引的現象,出現該現象的緣由有不少,該怎麼去定位呢?本文咱們主要就介紹這一部份內容

首先,咱們要肯定數據庫運行在何種優化模式下,相應的參數是: optimizer_mode 。可在 svrmgrl 中運行「 show parameter optimizer_mode" 來查看。 ORACLE V7 以來缺省的設置應是 "choose" ,即若是對已分析的表查詢的話選擇 CBO ,不然選擇 RBO 。若是該參數設爲「 rule 」,則不論表是否分析過,一律選用 RBO ,除非在語句中用 hint 強制。

其次,檢查被索引的列或組合索引的首列是否出如今 PL/SQL 語句的 WHERE 子句中,這是「執行計劃」能。

第三,看採用了哪一種類型的鏈接方式。 ORACLE 的共有 Sort Merge Join ( SMJ )、 Hash Join ( HJ )和 Nested Loop Join ( NL )。在兩張錶鏈接,且內表的目標列上建有索引時,只有 Nested Loop 纔能有效地利用到該索引。 SMJ 即便相關列上建有索引,最多隻能因索引的存在,避免數據排序過程。 HJ 因爲須作 HASH 運算,索引的存在對數據查詢速度幾乎沒有影響。

第四,看鏈接順序是否容許使用相關索引。假設表 emp 的 deptno 列上有索引,表 dept 的列 deptno 上無索引, WHERE 語句有 emp.deptno=dept.deptno 條件。在作NL 鏈接時, emp 作爲外表,先被訪問,因爲鏈接機制緣由,外表的數據訪問方式是全表掃描, emp.deptno 上的索引顯然是用不上,最多在其上。

第五,是否用到系統數據字典表或視圖。因爲系統數據字典表都未被分析過,可能致使極差的「執行計劃。

第六,是否存在潛在的數據類型轉換。如將字符型數據與數值型數據比較, ORACLE 會自動將字符型用to_number() 函數進行轉換,從而致使第六種現象的發生。

第七,是否爲表和相關的索引蒐集足夠的統計數據。對數據常常有增、刪、改的表最好按期對錶和索引進行分析,可用 SQL 語句「 analyze table xxxx compute statistics for all indexes;" 。 ORACLE 掌。

第八,索引列的選擇性不高。 咱們假設典型狀況,有表emp ,共有一百萬行數據,但其中的emp.deptno列,數據只有 4 種不一樣的值,如 10 、 20 、 30 、 40 。雖然 emp 數據行有不少, ORACLE 缺省認定表中列的值是在全部數據行均勻分佈的,也就是說每種 deptno 值各有 25 萬數據行與之對應。假設 SQL 搜索條件 DEPTNO=10 ,利用 deptno 列上的索引進行數據搜索效率,每每不比全表掃描的高, ORACLE 理不是在4 種deptno 值間平均分配,其中有99 萬行對應着值10 , 5000 行對應值 20 , 3000 行對應值 30 , 2000 行對應值 40 。在這種數據分佈圖案中對除值爲 10 外的其它 deptno 值搜索時,毫無疑問,若是索引能被應用,那麼效率會高出不少。咱們能夠採用對該索引列進行單獨分析,或用 analyze 語句對該列創建直方圖,對該列蒐集足夠的統計數據,使 ORACLE 在搜索選擇性較高的值能用上索引。

第九,索引列值是否可爲空( NULL )。若是索引列值能夠是空值,在 SQL 語句中那些須要返回 NULL 值的操做,將不會用到索引,如 COUNT ( * ),而是用全表掃描。這是由於索引中存儲值不能爲全空。

第十,看是否有用到並行查詢( PQO )。並行查詢將不會用到索引。如咱們想要用到A 表的IND_COL1 「 SELECT /*+ INDEX ( A IND_COL1 ) */ * FROM A WHERE COL1 = XXX;"注意,註釋符必須跟在SELECT以後,且註釋中的「 + 」要緊跟着註釋起始符「 /* 」或「 -- 」,不然 hint 就被認爲是通常註釋,對 PL/SQL 語句的執行不產生任何影響。
一種是 EXPLAIN TABLE 方式。

用戶必須首先在本身的模式( SCHEMA )下,創建 PLAN_TABLE 表,執行計劃的每一步驟都將記錄在該表中,建表 SQL 腳本爲在 ${ORACLE_HOME}/rdbms/admin/ 下的 utlxplan.sql 打開 SQL*PLUS ,輸入「 SET AUTOTRACE ON 」,而後運行待調試的 SQL 語句。在給出查詢結果後, ORACLE 將顯示相應的「執行計劃」,包括優化器類型、執行代價、鏈接方式、鏈接順序、數據搜索路徑以若是咱們不能肯定須要跟蹤的具體 SQL 語句,好比某個應用使用一段時間後,響應速度突然變慢。咱們這時能夠利用 ORACLE 提供的另外一個有力工具 TKPROF ,對應用的執行過程全程跟蹤。

咱們要先在系統視圖 V$SESSION 中,可根據 USERID 或 MACHINE ,查出相應的 SID 和 SERIAL# 。以SYS 或其餘有執行 DBMS_SYSTEM 程序包的用戶鏈接數據庫,執行「 EXECUTE DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION ( SID , SERIAL# , TRUE );」。而後運行應用程序,這時在服務器端,數據庫參「 USER_DUMP_DEST 」指示的目錄下,會生成 ora__xxxx.trc 文件,其中 xxxx 爲被跟蹤應用的操做系統進程號。應用程序執行完成後,用命令 tkprof 對該文件進行分析。

命令示例:「 tkprof tracefile outputfile explain=userid/password" 。在操做系統 ORACLE 用戶下,鍵入「 tkprof 」,會有詳細的命令幫助。分析後的輸出文件 outputfile 中,有每一條 PL/SQL 語句的「執行計劃」、 CPU 佔用、物理讀次數、邏輯讀次數、執行時長等重要信息。根據輸出文件的信息,咱們能夠很快發現應用中哪條 PL/SQL 語句是問題的癥結所在。

關於Oracle數據庫不能使用索引的緣由定位就介紹到這裏了,但願本次的介紹可以對您有所幫助。

相關文章
相關標籤/搜索