oracle中的索引选择行为,如果同一列上有多个索引

时间:2014-09-20 11:54:16

标签: oracle

如果列在两个索引之间是通用的,我在oracle中没有获得索引选择行为。

以下是示例代码:

create table emp 
(id number,
dpt number);

我在这张桌子上有两个索引:

create unique index ind1 on emp (id);
create unique index ind2 on emp (id,dpt);

这是我使用的数据:

Insert into EMP (ID,DPT) values (1,2);
Insert into EMP (ID,DPT) values (2,2);
Insert into EMP (ID,DPT) values (3,2);

当我根据某些过滤条件(例如

)获取数据时
select * from emp where id =2;

根据解释计划使用IND2

当我使用范围查询IND1时:

select * from emp where id > 2;

我没有得到关于此类索引行为的任何具体原因。

这里是否使用任何特定逻辑来决定在每个查询中使用哪个索引。

1 个答案:

答案 0 :(得分:0)

对于单个查找,复合索引上的INDEX RANGE SCAN比它便宜 单列索引需要INDEX UNIQUE SCANTABLE ACCESS BY INDEX ROWID。复合索引可能更大并且具有更多分支,但每个叶包含结果所需的所有值。访问该额外分支比访问整个不同的数据结构(表段)便宜。

这是一个稍大的示例架构。问题中的DDL很有用,但要真正理解这些问题,添加样本数据并显示如何收集统计信息非常重要。

create table emp(id number,dpt number);
create unique index ind1 on emp (id);
create unique index ind2 on emp (id,dpt);
insert into emp select level,level from dual connect by level <= 100000;
begin
    dbms_stats.gather_table_stats(user, 'emp');
end;
/

在问题中,默认计划使用IND2。

explain plan for select * from emp where id=2;
select * from table(dbms_xplan.display);

Plan hash value: 1519675770

-------------------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |    10 |     2   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IND2 |     1 |    10 |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------

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

   1 - access("ID"=2)

提示显示IND1计划的样子。请注意,现在计划必须同时访问索引和表。

explain plan for select /*+ index(emp ind1) */ * from emp where id =2;
select * from table(dbms_xplan.display);

Plan hash value: 2624671090

------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |     1 |    10 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP  |     1 |    10 |     2   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | IND1 |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------

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

   2 - access("ID"=2)

这只回答了第一个问题。我对第二个问题没有很好的解释。如果您可以修改示例数据以重新创建该场景,我们可以对其进行调查。