2017-03-09 11 views
0

私は100万行のテーブルAを持っています。 '03または '04'の値を持つpoliespa列のインデックスがあります。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. 

オプティマイザがインデックスを使用しない理由、またはこれが最善のアプローチである理由を理解できたら助けてください。おかげ

EDIT:サブセットは、テーブル全体の重要な一部である場合、それはインデックスを使用することが有益ではありません経験則として

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)*/from table – justMe

+4

'poliespa'に2つの値しかない場合は、おそらくインデックスを価値あるものにするためにスキャンする必要がある行の数を十分に減らさないでしょう。 –

+2

[フルスキャンは悪くありません。インデックスはすべての善ではありません](https://asktom.oracle.com/pls/asktom/f?p=100:11::::P11_QUESTION_ID:37453890985588)... –

答えて

2

。たとえば、20%の行に沿ったもの(ただし、それは明らかに異なります)。

なぜですか?

インデックスを介してこのデータにアクセスすると何が起こるかを考えてみましょう。インデックスを1つずつ持つブロック(インデックス全体のインデックスになる可能性があります)とテーブルのブロックにアクセスします。どのようにデータがテーブル(クラスタリング係数)に格納されるかを考えると、索引アクセスは結局はテーブル全体を読み取ることになります。

テーブルスキャンは、1つずつデータにアクセスするのではなく、マルチブロック読み取りを使用してすべてのブロックを順番に処理することができるため、より高速で高速に処理できます。

+0

私はボトルネックを考えていたので、ドライブからデータをフェッチするように(RDBMSによるブロックの要求を処理する手段として)私はブロックの代わりにページを使用していましたが、それはちょっとした違いだと思います。 – nimdil

0

答えは...

コスト

Oracleは、コストベースのオプティマイザを使用しています。 Oracleがフル・テーブル・スキャンのコストをインデックス・ルックアップのコストよりも低いと考える場合、フル・テーブル・スキャンが選択されます。

したがって、問合せのためのExplain計画を提供しました。それは良い。一歩進んでランタイム診断を取得しましょう:

alter session set timed_statistics=ALL; 

<run your query> 

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

ここで、インデックスを強制的に使用するようにヒントを追加します。クエリを再度実行し、上記のステートメントを使用して、インデックスプランの実行計画を取得します。

関連する問題