关于Oracle 9i 跳跃式索引扫描(Index Skip Scan)的小测试

oracle|索引

在Oracle9i中我们知道能够使用跳跃式索引扫描(Index Skip Scan).然而,能利用跳跃式索引扫描的情况其实是有些限制的.

从Oracle的文档中我们可以找到这样的话:

Index Skip Scans
Index skip scans improve index scans by nonprefix columns.
Often, scanning index blocks is faster than scanning table data blocks.
Skip scanning lets a composite index be split logically into smaller subindexes.
In skip scanning, the initial column of the composite index is not specified in the query.
In other words, it is skipped.

The number of logical subindexes is determined by the number of distinct values in the initial column.
Skip scanning is advantageous if there are few distinct values in the leading column of the composite
index and many distinct values in the nonleading key of the index.

也可以这样说,优化器根据索引中的前导列(索引到的第一列)的唯一值的数量决定是否使用Skip Scan.

我们首先做个测试:

SQL> CREATE TABLE test AS
  2  SELECT ROWNUM a,ROWNUM-1 b ,ROWNUM-2 c,ROWNUM-3 d,ROWNUM-4 e
  3  FROM all_objects
  4  /

SQL> SELECT DISTINCT COUNT (a) FROM test;

  COUNT(A)
----------
     28251

表已创建。

SQL>
SQL> CREATE INDEX test_idx ON test(a,b,c)
  2  /

索引已创建。

SQL> ANALYZE TABLE test COMPUTE STATISTICS
  2  FOR TABLE
  3  FOR ALL INDEXES
  4  FOR ALL INDEXED COLUMNS
  5  /

表已分析。

SQL> SET autotrace traceonly explain
SQL> SELECT *  FROM test WHERE b = 99
  2  /

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=36 Card=1 Bytes=26)
   1    0 TABLE ACCESS (FULL) OF 'TEST' (Cost=36 Card=1 Bytes=26)

--可见这里CBO选择了全表扫描.

--我们接着做另一个测试:

SQL> drop table test;

表已丢弃。

SQL> CREATE TABLE test
  2  AS
  3  SELECT DECODE(MOD(ROWNUM,2), 0, '1', '2' ) a,
  4                    ROWNUM-1 b,
  5                    ROWNUM-2 c,
  6                    ROWNUM-3 d,
  7                    ROWNUM-4 e
  8    FROM all_objects
  9  /

表已创建。

SQL> set autotrace off
SQL> select distinct a from test;

A
--
1
2

--A列只有两个唯一值

SQL> CREATE INDEX test_idx ON test(a,b,c)
  2  /

索引已创建。

SQL> ANALYZE TABLE test COMPUTE STATISTICS
  2  FOR TABLE
  3  FOR ALL INDEXES
  4  FOR ALL INDEXED COLUMNS
  5  /

表已分析。

SQL> set autotrace traceonly explain
SQL> SELECT *  FROM test WHERE b = 99
  2  /

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=1 Bytes=24)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST' (Cost=4 Card=1 Bytes=24)
   2    1     INDEX (SKIP SCAN) OF 'TEST_IDX' (NON-UNIQUE) (Cost=3 Card=1)

 

Oracle的优化器(这里指的是CBO)能对查询应用Index Skip Scans至少要有几个条件:

1 优化器认为是合适的.
2 索引中的前导列的唯一值的数量能满足一定的条件.
3 优化器要知道前导列的值分布(通过分析/统计表得到)
4 合适的SQL语句
......

更多信息请参考:

http://www.itpub.net/showthread.php?threadid=85948

http://www.cnoug.org/bin/ut/topic_show.cgi?id=608&h=1&bpg=1&age=100

http://www.itpub.net/showthread.php?s=&postid=985602#post985602

Oracle9i Database Performance Tuning Guide and Reference Release 2 (9.2)
Part Number A96533-02

感谢参加讨论的各位高手.

时间: 2024-12-28 07:48:08

关于Oracle 9i 跳跃式索引扫描(Index Skip Scan)的小测试的相关文章

【每日一摩斯】-Index Skip Scan Feature (212391.1)

INDEX Skip Scan,也就是索引快速扫描,一般是指谓词中不带复合索引第一列,但扫描索引块要快于扫描表的数据块,此时CBO会选择INDEX SS的方式. 官方讲的,这个概念也好理解,如果将复合索引看做是一个分区表,其中分区主键(这里指的是复合索引的首列)定义了存储于此的分区数据.在每个键(首列)下的每行数据都将按照此键排序.因此在SS,首列可以被跳过,非首列可以作为逻辑子索引访问.因此一个"正常"的索引访问可以忽略首列. 复合索引被逻辑地切分成更小的子索引.逻辑子索引的个数取决

跳跃式索引(Skip Scan Index)浅析

在Oracle9i中,有一个新的特性:跳跃式索引(Skip Scan Index).当表有一个复合索引,而在查询中有除了索引中第一列的其他列作为条件,并且优化器模式为CBO,这时候查询计划就有可能使用到SS.此外,还可以通过使用提示index_ss(CBO下)来强制使用SS. 举例: SQL> create table test1 (a number, b char(10), c varchar2(10)); Table created. SQL> create index test_idx1

《高并发Oracle数据库系统的架构与设计》一2.1 索引扫描识别

2.1 索引扫描识别 如果把我们的数据库比喻成一座图书馆,那表作为数据的载体,则是一本一本的图书,而索引则是图书的目录.目录不仅让图书阅读和查找变得方便,更是图书成败的关键. 也许有人会说,我翻阅的是一本杂志,内容本就不多,我甚至不需要目录.是的,Oracle数据库也考虑到了这一点,对于数据量很小的表,我们可以不建索引,在查询时可以进行全表扫描(FULL TABLE SCAN),这种方式对于小表来说更适合.但是,如果我们手上是一本大字典呢?你甚至一个人都搬不动它,当然你也不必像看杂志一样每页都去

Oracle Index Skip Scans使用场景

INDEX跳跃扫描一般用在WHERE条件里面没有使用到引导列,但是用到了引导列以外的其他列,并且引导列的DISTINCT值较少的情况. 在这种情况下,数据库把这个复合索引逻辑上拆散为多个子索引,依次搜索子索引中非引导列的WHERE条件里面的值. 使用方法如下: /*+ INDEX_SS ( [ @ qb_name ] tablespec [ indexspec [ indexspec ]... ] ) */ The  INDEX_SS hint instructs the optimizer t

Oracle 索引扫描的五种类型

Oracle 索引扫描的五种类型 (1)索引唯一扫描(INDEX UNIQUE SCAN) LHR@orclasm > set line 9999 LHR@orclasm > select * from scott.emp t where t.empno=10;   Execution Plan ---------------------------------------------------------- Plan hash value: 2949544139   -----------

Oracle索引扫描的4个类别

学习Oracle时,你可能会遇到Oracle索引扫描问题,这里将介绍Oracle索引扫描问题的解决方法,在这里拿出来和大家分享一 下.根据索引的类型与where限制条件的不同,有4种类型的Oracle索引扫描: ◆索引唯一扫描(index unique scan) ◆索引范围扫描(index range scan) ◆索引全扫描(index full scan) ◆索引快速扫描(index fast full scan) (1) 索引唯一扫描(index unique scan) 通过唯一索引查

关于索引扫描的极速调优实战(第一篇)

一般在生产环境中,如果某个查询中涉及一个大表,走索引扫描是显然是最值得推荐的方式,但是索引扫描有unique index scan, range scan,skip scan, full scan, fast full scan,这些索引扫描看起来好像很繁杂,但是如果掌握得当,却能够在索引扫描的基础上极速提升性能.关于索引扫描的方式,可以参考.http://blog.itpub.net/23718752/viewspace-1335358/ 关于索引的使用模式  首先来看看这个问题. 开发反应这

关于索引扫描的极速调优实战(第二篇)

在上一篇http://blog.itpub.net/23718752/viewspace-1364914/ 中我们大体介绍了下问题的情况,已经初步根据awr能够抓取到存在问题的sql语句. 这条sql语句执行很频繁,目前平均执行时间在0.5秒.开发部门希望我们能不能做点优化,他们也在同时想办法从业务上来优化这个问题.从0.5秒的情况下,能够再提高很多,是得费很大力气的. 况且这个问题比较紧急,从拿到sql语句开始,就感觉到一种压力. 最开始的注意力都集中在cycle_month和cycle_ye

oracle index unique scan/index range scan和mysql range/const/ref/eq_ref的区别

关于oracle index unique scan/index range scan和mysql range/const/ref/eq_ref type的区别    关于ORACLE index unique scan和index range scan区别在于是否索引是唯一的,如果=操作谓词有唯一索引则使用unique scan否则则使用range scan 但是这种定律视乎在MYSQL中不在成立 如下执行 kkkm2 id为主键 mysql> explain extended select