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)我是否需要在编制索引日期时采取任何预防措施?
答案 0 :(得分:3)
当你没有在谓词中指定索引的前导列时,Oracle确实能够通过索引跳过扫描来使用复合索引。然而,这通常比常规索引扫描效率低得多。从概念上讲,您可以将其视为对索引的前导列的每个不同值执行索引扫描。通常情况下,如果前导列具有一些不同的值且尾随列特别具有选择性,则Oracle仅考虑此类计划。我不希望在这里要么是真的 - 大概ename
几乎是独一无二的,job
选择性较差。我希望对表格进行全面扫描会更有效率,所以我猜想你的统计数据是“不可思议的”#34;如果您的表格特别小,那肯定会导致查询计划不寻常,因为每个计划看起来都非常便宜。
在现实世界中,极少数情况下有人会看到"索引跳过扫描"在查询计划中并且认为"太棒了!这就是我想要的计划。"它通常意味着某些事情出了问题,但它可能没有像它可能有的那么严重。
答案 1 :(得分:2)
好问题。
显然,如果您的查询同时包含ENAME
和JOB
,则Oracle会使用索引,使用INDEX RANGE SCAN
或INDEX 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个字节。