Oracle執行計划不走索引的原因總結


Oracle數據庫操作中,為什么有時一個表的某個字段明明有索引,當觀察一些語的執行計划確 不走索引呢?如何解決呢?本文我們主要就介紹這部分內容,接下來就讓我們一起來了解一下。

不走索引大體有以下幾個原因:

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

解決方法:

可以修改init.ora中的OPTIMIZER_MODE這個參數,把它改為Rule或Choose,重起數據庫。也可以使用4中所提的Hint。

不走索引的其它原因:

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

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

3、在索引列上使用函數時不會使用索引,如果一定要使用索引只能建立函數索引。

4、當被索引的列進行隱式的類型轉換時不會使用索引。如: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),此查詢會走索引。

5、並不是所有情況使用索引都會加快查詢速度,full scan table 有時會更快,尤其是當查詢的數據量占整個表的比重較大時,因為full scan table采用的是多塊讀,當Oracle優化器沒有選擇使用索引時不要立即強制使用,要充分證明使用索引確實查詢更快時再使用強制索引。

6、<>

7、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數據庫不能使用索引的原因定位就介紹到這里了,希望本次的介紹能夠對您有所幫助。


免責聲明!

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



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