2017-03-09 68 views
0

我有一個100萬行的表A.我有一個poliespa列'03或'04'值的索引。Oracle沒有使用索引

CREATE INDEX A21 ON A(POLIESPA); 

我的查詢:

 SELECT polinpol, 
     policdde, 
     polipext, 
     polidext, 
     DECODE (polipext, 'T', polipdmx, 'A', polipdmx, polipdix), 
     politipo, 
     polipdtu, 
     DECODE (TO_NUMBER (RTRIM (LTRIM (polivmrd))), 0, 0, polivmrd), 
     RTRIM (LTRIM (polipdtx)), 
     polifeca 
    FROM A 
WHERE poliespa = '03'; 

這個SQL查詢的解釋計劃,使全表掃描:

Plan hash value: 3450718889 

---------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
---------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  | 369K| 14M| 6615 (3)| 00:00:01 | 
|* 1 | TABLE ACCESS FULL| A  | 369K| 14M| 6615 (3)| 00:00:01 | 
---------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter("POLIESPA"='03') 

塊 - 41735:

SELECT COUNT (
      DISTINCT (SUBSTR (DBMS_ROWID.rowid_to_restricted (ROWID, 1), 1, 8))) 
      blocks 
    FROM A; 

集羣:

SELECT index_name, clustering_factor 
    FROM user_indexes 
WHERE index_name LIKE 'A21%' 

INDEX_NAME CLUSTERING_FACTOR 
----------------- 
A21   79247 

1 row selected. 

任何人都可以幫助我理解爲什麼優化器不使用索引或爲什麼這是最好的方法?由於

編輯:

select count(*) from A 
where poliespa = '03'; 

select count(*) from A 
where poliespa = '04'; 

    COUNT(*) 
---------- 
    221379 
1 row selected. 

    COUNT(*) 
---------- 
    517095 
1 row selected. 
+0

嘗試使用提示,文檔這裏https://docs.oracle.com/cd/B12037_01/server.101/b10752/hintsref.htm看看是否有幫助。類似於select/* + INDEX(table_name index_name)* /從表 – justMe

+4

如果'poliespa'只有兩個值,那麼使用它可能不足以減少需要掃描的行數,以使索引值得。 –

+2

[完整掃描並非邪惡;索引是不是所有的善良](https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:37453890985588)... –

回答

2

作爲一個經驗法則,如果子集是整個表的顯著部分是不利於使用索引。例如,沿20%的線(但很明顯取決於)。

爲什麼?

想想,當你通過索引來訪問這些數據會發生什麼 - 你訪問塊索引一個-AT-A-時間(和給定的比例也可以是不亞於整體指數)加上表的塊。鑑於數據可能如何存儲在表上(聚類因子),索引訪問可能最終會讀取整個表。

表掃描可以更好,更快,你可以只通過依次所有塊使用多塊讀取,而不是訪問一個-AT-A-時間數據去。

+0

我正在使用頁面而不是塊,因爲我在考慮瓶頸,所以OS從驅動器獲取數據(作爲通過RDBMS處理塊請求的方式),但我想這是微不足道的差異。 – nimdil

0

答案是...

成本

Oracle使用一個基於成本的優化。如果Oracle認爲全表掃描的成本低於索引查找的成本,那麼它將選擇全表掃描。

所以你提供瞭解釋計劃給你查詢;那很好。讓我們走一步,並獲得運行時診斷:

alter session set timed_statistics=ALL; 

<run your query> 

select * from table(dbms_xplan.display_cursor(null, null, 'ALLSTATS LAST)); 

現在添加一個提示您查詢強制使用索引。再次運行查詢,並使用上述語句獲取索引計劃的執行計劃。