了解Oracle索引顺序

时间:2015-06-22 19:52:59

标签: oracle indexing

我对此有点困惑,希望有人可以提供帮助。我正在通过Markus Winand的优秀Use The Index Luke书阅读这本关于连锁索引的事情。

在查询

时创建了(EMPLOYEE_ID, SUBSIDIARY_ID)个索引
SELECT first_name, last_name
  FROM employees
 WHERE subsidiary_id = 20

这个执行计划出现了:

----------------------------------------------------
| Id | Operation         | Name      | Rows | Cost |
----------------------------------------------------
|  0 | SELECT STATEMENT  |           |  106 |  478 |
|* 1 |  TABLE ACCESS FULL| EMPLOYEES |  106 |  478 |
----------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("SUBSIDIARY_ID"=20)

但事情就是这样:在我自己的员工表(empno, ename, init, job, mgr, bdate, msal, comm, deptno)上,我在(ENAME, JOB)上创建了一个连锁索引

查询select ename from employees where job = 'TRAINER';为我提供了以下执行计划:

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

Plan hash value: 4271702361

--------------------------------------------------------------------------------

| Id  | Operation        | Name        | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------------

|   0 | SELECT STATEMENT |             |     3 |    45 |     1   (0)| 00:00:01 |

|*  1 |  INDEX SKIP SCAN | ENAME_INDEX |     3 |    45 |     1   (0)| 00:00:01 |

--------------------------------------------------------------------------------


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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------


   1 - access("JOB"='TRAINER')
       filter("JOB"='TRAINER')

所以现在我有点困惑。

1)怎么来,尽管订单,我的索引仍在使用?

2)索引跳过扫描是否适用于我没有在where子句中使用第一列的任何连锁索引?

3)索引跳过扫描是否会对性能产生重大影响?

4)怎么会有访问权限和过滤谓词?

虽然我在这里,但还有另外一个问题

5)我是否需要在编制索引日期时采取任何预防措施?

3 个答案:

答案 0 :(得分:3)

当你没有在谓词中指定索引的前导列时,Oracle确实能够通过索引跳过扫描来使用复合索引。然而,这通常比常规索引扫描效率低得多。从概念上讲,您可以将其视为对索引的前导列的每个不同值执行索引扫描。通常情况下,如果前导列具有一些不同的值且尾随列特别具有选择性,则Oracle仅考虑此类计划。我不希望在这里要么是真的 - 大概ename几乎是独一无二的,job选择性较差。我希望对表格进行全面扫描会更有效率,所以我猜想你的统计数据是“不可思议的”#34;如果您的表格特别小,那肯定会导致查询计划不寻常,因为每个计划看起来都非常便宜。

在现实世界中,极少数情况下有人会看到"索引跳过扫描"在查询计划中并且认为"太棒了!这就是我想要的计划。"它通常意味着某些事情出了问题,但它可能没有像它可能有的那么严重。

答案 1 :(得分:2)

好问题。

显然,如果您的查询同时包含ENAMEJOB,则Oracle会使用索引,使用INDEX RANGE SCANINDEX UNIQUE SCAN。但是,查询谓词中未提供索引的前沿ENAME。因此,Oracle的基于成本的优化器(CBO)有一个选择。它可以选择FULL TABLE SCAN(忽略索引)或INDEX SKIP SCAN

我假设你知道FULL TABLE SCAN是什么,所以我不会进入那个。

那么,INDEX SKIP SCAN是什么?那么,根据索引的形状和大小,CBO可以选择跳过扫描。当索引中的前导列存在相对较少的不同值时,通常会发生这种情况。会发生什么,Oracle获取索引并有效地将其分解为多个索引。假设前导列有4个不同的值,(1-4)。因此,Oracle查看索引的子集,其中前导列等于1,并对索引的该子集进行范围扫描,然后对索引的子集执行相同的操作,其中前导列等于2,然后是3,然后是4。在某些情况下,根据前导列具有多少个不同的值以及第二列上的范围扫描的选择性,此访问路径的成本可能低于FULL TABLE SCAN

这是另一个原因,如果所有其他条件相同,您可能希望在索引的前沿放置 less 选择列。 (压缩的另一个主要原因。)

希望有所帮助。

答案 2 :(得分:0)

大多数问题的答案:https://oracle-base.com/articles/9i/index-skip-scanning

1)这正是INDEX SKIP SCAN的用途。

2)是的,它可以使用,但这取决于你的统计数据

3)它可能也可能不会 - >取决于您的统计信息

4)访问路径是关于选择要加载的数据块,过滤是关于如何过滤掉来自数据块的行。

5)DATE上的索引与其他数据类型的索引非常相似。 DATE长7个字节。