Oracleにインデックス範囲スキャンの使用を「強制」するには、オプティマイザヒントINDEX_RS_ASC
を使用するだけです。 。例:
CREATE TABLE mytable (a NUMBER NOT NULL, b NUMBER NOT NULL, c CHAR(10)) NOLOGGING;
INSERT /*+ APPEND */ INTO mytable(a,b,c)
SELECT level, mod(level,100)+1, 'a' FROM dual CONNECT BY level <= 1E6;
CREATE INDEX myindex_ba ON mytable(b, a);
EXECUTE dbms_stats.gather_table_stats(NULL,'mytable');
SELECT /*+ FULL(m) */ b FROM mytable m WHERE b=10; -- full table scan
SELECT /*+ INDEX_RS_ASC(m) */ b FROM mytable m WHERE b=10; -- index range scan
SELECT /*+ INDEX_FFS(m) */ b FROM mytable m WHERE b=10; -- index fast full scan
これによりクエリが実際に高速になるかどうかは、インデックス値の選択性やテーブル内の行の物理的な順序など、多くの要因によって異なります。たとえば、クエリをWHERE b BETWEEN 10 AND <xxx>
に変更した場合 、次のコストが私のマシンの実行プランに表示されます:
b BETWEEN 10 AND 10 20 40 80
FULL 749 750 751 752
INDEX_RS_ASC 29 325 865 1943
INDEX_FFS 597 598 599 601
クエリをごくわずかに変更して、インデックス付きの列b
を選択するだけではない場合 、だけでなく、他のインデックス以外の列でも、コストは劇的に変化します:
b BETWEEN 10 AND 10 20 40 80
FULL 749 750 751 754
INDEX_RS_ASC 3352 40540 108215 243563
INDEX_FFS 3352 40540 108215 243563