【问题标题】:Index selection behaviour in oracle in case of multiple indexes on same columns在同一列上有多个索引的情况下,oracle 中的索引选择行为
【发布时间】:2014-11-14 21:48:32
【问题描述】:

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

下面是示例代码:

create table emp 
(id number,
dpt number);

我在这张表上有 2 个索引:

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;

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

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

【问题讨论】:

  • @Jon Heller...感谢您的 cmets。使用我使用的数据进行了更新。但现在,奇怪的是,这两个查询都仅使用索引 IND2,而之前的行为有所不同。跨度>
  • 这很奇怪,这甚至是可能的。在较旧的 Oracle 版本中,有一个限制,即在一个索引上设置的列不能是其他索引的“前缀”。

标签: oracle


【解决方案1】:

对于单个查找,复合索引上的 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)

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

【讨论】:

    猜你喜欢
    • 2017-01-20
    • 2022-01-21
    • 2021-07-09
    • 2015-03-24
    • 2021-10-30
    • 2019-02-08
    • 2011-03-31
    相关资源
    最近更新 更多