我有 table
test_A(
id1 number,
id2 number,
id3 number,
name varchar2(10),
create_dt date
)
我有两个索引,一个是 (id1,id2)
上的复合索引 indx1
和 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
上创建另一个索引,或者索引跳过扫描是否有效?我相信索引跳过是 Oracle 运行多个索引范围扫描的一个功能?
最佳答案
我建议您熟悉此链接: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);
关于oracle - 索引范围扫描 vs 索引跳过扫描 vs 索引快速全扫描,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19059444/