為何在查詢中索引未被使用 (文件 ID 1549181.1)
文件內容
適用於:
Oracle Database - Standard Edition - 版本 8.1.7.4 和更高版本
Oracle Database - Personal Edition - 版本 8.1.7.4 和更高版本
Oracle Database - Enterprise Edition - 版本 8.1.7.4 和更高版本
本文件所含資訊適用於所有平臺
用途
這篇文章用來解答下面的問題:為什麼我的索引沒有被使用?
排錯步驟
“為什麼索引沒有被使用”是一個涉及面較廣的問題。有很多種原因會導致索引沒有被使用。下面是一些非常有用的檢查列表。請點選下面連結來檢視文章的具體內容:
快速檢查
-
表上是否存在索引?
檢查您認為應該透過索引訪問的表上是否真的有定義索引。那些索引可能已經被刪掉或者在建立的時候就失敗了 – 比如一種可能的場景是,在對錶做匯入或 load 操作後,由於軟體或人為錯誤造成索引沒有被建立。下面的語句可以用來檢查索引是否存在。
SELECT index_name FROM user_indexes WHERE table_name = &Table_Name;
-
索引是否應該被使用?
Oracle
不會僅僅因為有索引存在就一定要使用索引。如果一個查詢需要檢索出這個表裡所有的記錄(比如說表之間做連線操作),那為什麼還要既訪問索引的所有資料又訪問表的所有資料呢?在這種情況下只訪問表的資料會更快。對所有的查詢
Oracle Optimizer 會基於統計資訊來計算各種訪問路徑,包括索引,從而選出最優的一個。
索引本身的問題
最佳化器和成本計算相關問題
-
是否存在準確且合適的統計資訊(Statistics)?
CBO 依賴於準確的、最新的和完整的統計資訊來確定一個特定查詢的最佳執行計劃。如果使用 CBO,請確保統計資訊已經收集。如果沒有統計資訊, CBO 將使用預定義的統計資訊,這樣是很可能不會產生良好的計劃或讓應用程式使用索引。請參照:
Document 754931.1 Cost Based Optimizer - Common Misconceptions and Issues - 10g and Above
-
請注意,CBO 會根據開銷(COST)來決定使用不同的索引。除了基本的表和索引的資訊之外,如果說在某些列上資料分佈是不均勻的,那麼還需要收集這些列的資料的分佈。關於收集統計資訊的建議,請參見以下文件:
在一般情況下,物件的資料或結構的改變會使以前的統計資訊不準確,因此應該重新收集新的統計資訊。例如,對錶裝載了大量的資料後,需要收集新的統計資訊。安裝新補丁集(Patchset)後,也建議重新收集統計資訊。表訪問最佳效果是統計資訊是在相同版本的資料庫中生成的。
下邊的文件討論了為什麼資料庫升級後查詢的效能會下降:
-
一個索引是否與其它的索引有相同的等級或者成本(cost)?
對於相同開銷(COST)的索引,CBO 會使用多種辦法將不同的索引區分開,如將索引名稱按字母順序排序,完全匹配的索引掃描會選擇更大的NDK(不同鍵值的個數)的索引(不適用於快速全掃描)或選擇葉塊數量較少的索引。請注意一般很少發生這種情況。 請檢視
-
索引的選擇度不高?
-
索引的選擇度不高
使用它可能不是一個好的選擇...
列資料不是平均分佈的。
-
CBO 假定列資料不會傾斜,並均勻分佈。如果不是這樣,那麼統計資訊可能沒有反映真實情況,那麼即使某些值的選擇度高,索引也會因為整個列的選擇度不高而不適用索引。 如果是這種情況,那麼應考慮採用直方圖記錄更準確的列的資料分佈或者採用提示(hint)。
-
統計資訊不準確導致索引看起來選擇性不高而不被選擇。可能的規避方法:
-
收集更精確的統計值。 請檢視
-
對於資料分佈不均勻的列考慮收集列的統計資訊
-
使用 hint 或 outline。請參考
-
在總體成本中,表掃描的成本佔大部分
通常來說,當使用索引的時候,我們需要再次檢索表本身來找到索引中不存在的欄位的值,這個操作比檢索索引本身的開銷要大很多。由於 optimizer
是基於總體的成本來計算執行計劃,如果透過索引檢索表的成本很大,並且超過了某個閥值,optimizer 就會考慮其他的訪問路徑。
比如
SELECT empno FROM emp WHERE empno=5
這條語句可能會使用基於列 empno的索引,因為所有需要的資料都存放在索引中所以不需要再對錶做而外的訪問。反之:
SELECT ename FROM emp WHERE empno=5
這條語句會需要對錶做而外的訪問,因為 ename 欄位沒有存放在索引中。檢索 ename 的開銷會隨著查詢返回記錄條數的增加而變得昂貴。
Optimizer 使用"Clustering Factor"來判斷如果使用 index 的話需要而外對錶做多少次訪問,詳見:
-
訪問空索引並不意味著比訪問有值的索引高效。
Reorganization, Truncation 或刪除操作不一定會影響 SQL
語句執行的成本。需要注意的是刪除操作並不會從物件中真正釋放空間。也就是說,刪除操作不會重置物件的高水位線。Truncate
操作會重置高水位線。空塊的存在會使索引/表掃描的成本比實際應該的成本高。刪掉並重建會重組物件的結構從而有可能會有幫助(也有可能變壞)。這類問題通常在比較兩個有相同資料的不同系統查詢效能時更容易看到。
-
引數設定
某些引數的設定可能會影響索引的使用。比如在大多數情況下都建議使用 DB_FILE_MULTIBLOCK_READ_COUNT 和
OPTIMIZER_INDEX_COST_ADJ
的預設值。除非某些特定的操作有特定的建議,使用其它值會使索引的成本不現實的減少或變大從而極大的降低查詢的效能。
其它問題
參考
NOTE:30779.1 - Init.ora Parameter "NLS_SORT" Reference Note
NOTE:67409.1 - When will an ORDER BY use an Index to Avoid Sorting?
NOTE:227335.1 - Linguistic Sorting - Frequently Asked Questions
NOTE:69992.1 - Why is my Hint Ignored?
NOTE:754931.1 - Cost Based Optimizer - Common Misconceptions and Issues - 10g and Above
NOTE:10577.1 - Driving ORDER BY using an Index (Oracle7)
NOTE:62153.1 - Optimization of Large Inlists / Multiple OR Conditions
NOTE:28426.1 - Partition Views and the use of Indexes (7.1 & 7.2)
NOTE:1369591.1 - Master Note: Optimizer Statistics
NOTE:44961.1 - Statistics Gathering: Frequency and Strategy Guidelines
NOTE:160089.1 - Troubleshooting a Server Upgrade Resulting in Slow Query Performance
NOTE:70135.1 - Index Fast Full Scan Usage To Avoid Full Table Scans
NOTE:43194.1 - Partition Views in 7.3: Examples and Tests
NOTE:50607.1 - How to specify an INDEX Hint
NOTE:212391.1 - Index Skip Scan Feature
NOTE:70067.1 - All about Bitmap Indexes
NOTE:28934.1 - Use of Indexes with NOT IN Subquery
NOTE:73167.1 - Handling of equally ranked (RBO) or costed (CBO) indexes
NOTE:199070.1 - Optimizing statements that contain views or subqueries
NOTE:68809.1 - Distributed Queries
NOTE:68084.1 - Using hints to optimize an Update with subquery not using index on updated table
NOTE:68992.1 - Predicate Selectivity
NOTE:344135.1 - Ordering of Result Data
NOTE:29236.1 - QREF: SQL Statement HINTS
|
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31393455/viewspace-2129678/,如需轉載,請註明出處,否則將追究法律責任。