索引范围扫描与索引跳过扫描与索引快速全扫描

时间:2013-09-27 20:21:47

标签: oracle indexing database-administration

我有桌子

test_A(
    id1 number,
    id2 number,
    id3 number,
    name varchar2(10),
    create_dt date
)

我在indx1(id1,id2)上有两个索引,一个复合索引indx2(id3)。现在,当我将此表test_A查询为

select * from test_A where id2=123 and 
create_dt=(select max(create_dt) from test_A where test_A.id2=id2);

我为上面的SQL运行了解释计划,它正在使用“索引跳过扫描”。如果我在create_dt上创建另一个索引,那么它使用索引快速全扫描并且所有成本和%cpu显示高于带有索引跳过扫描的计划。它在create_dt上创建索引后也使用索引范围扫描。

我无法得出应该可以得出的结论?我需要在create_dt上创建另一个索引还是索引跳过扫描好?我相信Index skip是Oracle运行多索引范围扫描的一个功能吗?

1 个答案:

答案 0 :(得分:3)

我建议您熟悉此链接:http://docs.oracle.com/cd/E16655_01/server.121/e15858/tgsql_optop.htm#CHDFJIJA
它与Oracle 12c相关,但是了解oracle如何在所有DBMS版本中使用不同的索引访问路径非常有用。


你的子查询是不明确的:

select max(create_dt) from test_A where test_A.id2=id2

test_A.id2和id2都引用相同的test_A.id2,查询等同于:

select * from test_A where id2=123 and 
create_dt=(select max(create_dt) from test_A where id2=id2);

或简单地说:

select * from test_A where id2=123 and 
create_dt=(select max(create_dt) from test_A where id2 is not null);



我想你想要这样的东西:

select * from test_A where id2=123 and 
create_dt=(select max(create_dt) 
           from test_A ALIAS 
           where test_A.id2=ALIAS.id2);

对于上面的查询,id2 + create_dt上的复合索引最有可能产生最佳效果,请尝试:

CREATE INDEX index_name ON test_A( id2, create_dt);