- 浏览: 68671 次
- 性别:
- 来自: 杭州
文章分类
最新评论
跳跃式索引(Skip Scan Index)的浅析
[English]
作者: fuyuncat
来源: www.HelloDBA.com
在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 on test1(a, b);
Index created.
SQL> set autotrace on
SQL> select /*+index_ss(test1 test_idx1)*/* from test1 a
2 where b ='a';
no rows selected
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=32)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST1' (Cost=2 Card=1 Bytes=32)
2 1 INDEX (SKIP SCAN) OF 'TEST_IDX1' (NON-UNIQUE)
但并不是任何情况下都会使用到SS。在Oracle的官方文档中,除了提到需要CBO,并且对表进行过分析外,还需要保证第一列的distinct value非常小。这一段是从官方文档上摘取的关于SS的一段解释:Index skip scans improve index scans by nonprefix columns since it is often faster to scan index blocks than scanning table data blocks.
In this case a composite index is split logically into smaller subindexes. The number of logical subindexes depends on the cardinality of the initial column. Hence it is now possible to use the index even if the leading column is not used in a where clause.
Oracle并没有公布过关于SS更多的内部技术细节。但注意上面的这句话:In this case a composite index is split logically into smaller subindexes. The number of logical subindexes depends on the cardinality of the initial column.即Oralce会对复合索引进行逻辑划分,分成多个子索引。可以这样理解,Oracle将索引从逻辑上划分为a.num_distinct个子索引,每次对一个子索引进行扫描。因此SS的索引扫描成本为a.num_distinct.
下面做一些试验,看看在什么情况下Oracle采用SS.
首先要保证使用SS的几个必要条件:
· Optimizer为CBO
· 相关表要有正确的统计数据
· Oracle DB版本为9i以上
下面就是一个使用到SS的特殊条件:第一列的distinct num要足够小。小到什么程度呢?
还是以上面的表为例(省略中间的麻烦步骤,取两个临界值做实验):
取第一列distinct number为37:
SQL> truncate table test1;
Table truncated.
SQL> begin
2 for i in 1..100000 loop
3 insert into test1 values (mod(i,37), to_char(i), to_char(i));
4 end loop;p;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> analyze table test1 compute statistics;
Table analyzed.
SQL> set autotrace on explain
SQL> select * from test1
2 where b = '500';
A B C
---------- ---------- ----------
19 500 500
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=17)
1 0 TABLE ACCESS (FULL) OF 'TEST1' (Cost=37 Card=1 Bytes=17)
再取第一列distinct number为36:
SQL> truncate table test1;
Table truncated.
SQL> begin
2 for i in 1..100000 loop
3 insert into test1 values (mod(i,36), to_char(i), to_char(i));
4 end loop;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> analyze table test1 compute statistics;
Table analyzed.
SQL> select * from test1 where b = '500';
A B C
---------- ---------- ----------
32 500 500
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=1 Bytes=17)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST1' (Cost=12 Card=1 B
ytes=17)
2 1 INDEX (SKIP SCAN) OF 'TEST_IDX1' (NON-UNIQUE) (Cost=37 C
ard=1)
从上面试验结果看,FTS的cost是37。当第一列distinct number小于这个值时,Oracle选择了SS。
继续试验:
SQL> select count(*) from test1
2 where b <= '1';
COUNT(*)
----------
1
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=1 Bytes=10)
1 0 SORT (AGGREGATE)
2 1 INDEX (SKIP SCAN) OF 'TEST_IDX1' (NON-UNIQUE) (Cost=37 C
ard=1 Bytes=10)
注意:在b中’10’是比’1’大的最小值(char(10)类型)
SQL> select count(*) from test1
2 where b <= '10';
COUNT(*)
----------
2
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=10)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'TEST1' (Cost=37 Card=773 Bytes=7
730)
观察结果,这时候影响的因素是cardinality了。第二个查询计划中的cardinality值(773)正是b<=’10’的cardinality值:
SQL> set autotrace off
SQL> select 100000*(to_number('31302020202020202020', 'xxxxxxxxxxxxxxxxxxxx')-to
_number('31202020202020202020', 'xxxxxxxxxxxxxxxxxxxx'))/(to_number('39393939392
020202020', 'xxxxxxxxxxxxxxxxxxxx')-to_number('31202020202020202020', 'xxxxxxxxx
xxxxxxxxxxx'))+1 from dual;
100000*(TO_NUMBER('31302020202020202020','XXXXXXXXXXXXXXXXXXXX')-TO_NUMBER('3120
--------------------------------------------------------------------------------
772.791768
再看一个含有第一列条件的等效的语句:
SQL> set autotrace on explain
SQL> select count(*) from test1
2 where a>=0
3 and b <='1';
COUNT(*)
----------
1
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=1 Bytes=12)
1 0 SORT (AGGREGATE)
2 1 INDEX (SKIP SCAN) OF 'TEST_IDX1' (NON-UNIQUE) (Cost=37 C
ard=1 Bytes=12)
再做几个有趣的试验,下面的试验条件是不满足SS的,但是请注意查询返回列队查询计划的影响:
SQL> truncate table test1;
Table truncated.
SQL> begin
2 for i in 1..100000 loop
3 insert into test1 values (i, to_char(i), to_char(i));
4 end loop;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> analyze table test1 compute statistics;
Table analyzed.
SQL> select * from test1
2 where b = '500';
A B C
---------- ---------- ----------
500 500 500
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=19)
1 0 TABLE ACCESS (FULL) OF 'TEST1' (Cost=37 Card=1 Bytes=19)
改变返回列:
SQL> select count(*) from test1
2 where b = '500';
COUNT(*)
----------
1
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=34 Card=1 Bytes=10)
1 0 SORT (AGGREGATE)
2 1 INDEX (FAST FULL SCAN) OF 'TEST_IDX1' (NON-UNIQUE) (Cost
=34 Card=1 Bytes=10)
再改变一种:
SQL> select a from test1
2 where b = '500';
A
----------
500
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=34 Card=1 Bytes=14)
1 0 INDEX (FAST FULL SCAN) OF 'TEST_IDX1' (NON-UNIQUE) (Cost=3
4 Card=1 Bytes=14)
使用RBO呢?
SQL> select /*+rule*/a from test1
2 where b = '500';
A
----------
500
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
1 0 TABLE ACCESS (FULL) OF 'TEST1'
值得一提的是,上述任何一个例子在8i中执行的话,都不会使用到索引(无论是否符合SS的条件)。
发表评论
-
Oracle Session 视图[转]
2013-03-06 10:17 940v$session v$session_wait v$ ... -
10G中查看历史执行计划信息[转]
2013-03-01 11:02 3735现在总结下10G的,使用的是AWR报告中的信息,主要是查询 ... -
DBMS_XPLAN.Display_Cursor 分析[转]
2012-12-27 10:49 941Oracle 10 added the awesome pro ... -
[转]解决ora-01652无法通过128(在temp表空间中)扩展temp段的过程
2012-11-28 11:11 818Tag: http://www.oraclefans. ... -
Estimate TEMP usage without running SQL [转]
2012-11-28 11:09 760Estimate TEMP usage without run ... -
[转]Optimizing SPLIT PARTITION and SPLIT SUBPARTITION Operations
2012-11-27 15:11 874Optimizing SPLIT PARTITION and ... -
Oracle splitting partitions简单小结[转]
2012-11-27 15:12 957http://www.oracleonlinux.cn/201 ... -
When the explanation doesn't sound quite right
2012-10-30 13:05 0When the explanatio ... -
Bind variables - The key to application performance[转]
2012-11-27 15:16 748Overview If you've been ... -
not in/not exists 的 null 陷阱
2012-09-27 11:07 0[转]not in/not exists 的 nul ... -
Oracle中组合索引的使用详解[转]
2012-11-27 15:15 764Oracle中组合索引的使用详解 在Oracle中可以创 ...
相关推荐
索引跳跃式扫描(index skip scan)是Oracle9i的一个新的执行特性,尤其适用于使用连接索引和访问多值索引的Oracle查询。Oracle9i的索引跳跃式扫描执行规则允许使用连接索引,即使SQL查询中不指定性别。 这一特性使得...
MySQL 8.0.13开始支持 index skip scan 也即索引跳跃扫描。该优化方式支持那些SQL在不符合组合索引最左前缀的原则的情况,优化器依然能组使用组合索引。 talk is cheap ,show me the code 实践 使用官方文档的例子...
4.索引跳跃扫描(INDEX SKIP SCAN) 5.索引快速全扫描(INDEX FAST FULL SCAN) 索引唯一扫描(INDEX UNIQUE SCAN) 通过这种索引访问数据的特点是对于某个特定的值只返回一行数据,通常如果在查询谓语中使用UNIQE和...
1:索引跳跃扫描的应用 2:索引失效与表move之间的关系
redis中使用的skiplist数据结构
跳跃式营销方案
跳跃式营销方案.doc
以HTV-2为基础,用matlab程序进行了跳跃式滑翔弹道的仿真
针对多数地区煤矿开采...探讨了跳跃式采煤生产布局在各系统方面的特点,分析了跳跃式采煤生产布局的优势所在,提出了跳跃式采煤生产布局的相关技术管理措施;为煤矿在深部复杂区域采用跳跃式采煤生产布局提供了参考依据。
参考资料-跳跃式营销方案.zip
探讨多点跳跃式无线网络于近年之研究趋势与模拟实验导引.pdf
编写环境 VS2008 支持 添加,插入,搜索,输出 等功能
CSS3实现的跳跃式loading加载动画特效源码.zip
跳表(skiplist)是一个非常优秀的数据结构,实现简单,插入、删除、查找的复杂度均为O(logN),下面这篇文章主要介绍了c++实现跳跃表(Skip List)的相关资料,需要的朋友可以参考借鉴,下面随着小编来一起学习学习...
OpenLeap, 一个用于跳跃式运动传感器的开源驱动的主动 OpenLeap一个用于跳跃式运动传感器的开源驱动的主动。我最近掌握了跳跃运动设备 [1] 。所谓"linux支持"实际上仅仅是 x86/x64 Ubuntu 12.04的专有二进制文件。 ...
跳跃表 skiplist 技术分享
主要介绍了Java编程中跳跃表的概念和实现原理,并简要叙述了它的结构,具有一定参考价值,需要的朋友可以了解下。
一、 目标:使用C++语言为任意书籍构造索引字典(英文书)。 二、 输入:书籍的文本文件;测试用例为Christmas.txt 三、 输出:包含索引的文本文件,包括排序后的英文字典,英文出现次数,出现该英文的页码。 用例...
C++ 实现的跳跃表skiplist,支持模板,参照Redis的zskiplist跳跃表实现, 支持模板,适合用来做排行榜