Oracle 索引的分类,分析与比较....
Oracle 索引的分类,分析与比较....(转载)
分类:Oracle 2015-10-22 11:05:09 原文地址:Oracle 索引的分类,分析与比较....(转载)作者:anyoracle 逻辑上: Single column 单行索引 Concatenated 多行索引 Unique 唯一索引 NonUnique 非唯一索引 Function-based函数索引 Domain 域索引 物理上: Partitioned 分区索引 NonPartitioned 非分区索引 B-tree: Normal 正常型B树 Rever Key 反转型B树 Bitmap 位图索引 索引结构: B-tree: 适合与大量的增、删、改(OLTP); 不能用包含OR操作符的查询; 适合高基数的列(唯一值多) 典型的树状结构; 每个结点都是数据块; 大多都是物理上一层、两层或三层不定,逻辑上三层; 叶子块数据是排序的,从左向右递增; 在分支块和根块中放的是索引的范围; Bitmap: 适合与决策支持系统; 做UPDATE代价非常高; 非常适合OR操作符的查询; 基数比较少的时候才能建位图索引; 树型结构: 索引头 开始ROWID,结束ROWID(先列出索引的最大范围) BITMAP 每一个BIT对应着一个ROWID,它的值是1还是0,如果是1,表示着BIT对应的ROWID有值;[@more@] Oracle索引分析与比较
首先给出各种索引的简要解释: b*tree index:几乎所有的关系型数据库中都有b*tree类型索引,也是被最多使用的。其树结构与二叉树比较类似,根据rid快速定位所访问的行。 2 各种索引的结构分析 2.1 B*Tree索引B*Tree索引是最常见的索引结构,默认建立的索引就是这种类型的索引。B*Tree索引在检索高基数数据列(高基数数据列是指该列有很多不同的值)时提供了最好的性能。当取出的行数占总行数比例较小时B-Tree索引比全表检索提供了更有效的方法。但当检查的范围超过表的10%时就不能提高取回数据的性能。B-Tree索引是基于二叉树的,由分支块(branch block)和叶块(leaf block)组成。在树结构中,位于最底层底块被称为叶块,包含每个被索引列的值和行所对应的rowid。在叶节点的上面是分支块,用来导航结构,包含了索引列(关键字)范围和另一索引块的地址。 假设我们要找索引中值为80的行,从索引树的最上层入口开始,定位到大于等于50,然后往左找,找到第2个分支块,定位为75-100,最后再定位到叶块上,找到80所对应的rowid,然后根据rowid去读取数据块获取数据。如果查询条件是范围选择的,比如where column >20 and column <80,那么会先定位到第一个包含20的叶块,然后横向查找其他的叶块,直到找到包含80的块为止,不用每次都从入口进去再重新定位。 2.2 反向索引 反向索引是B*Tree索引的一个分支,它的设计是为了运用在某些特定的环境下的。Oracle推出它的主要目的就是为了降低在并行服务器(Oracle Parallel Server)环境下索引叶块的争用。当B*Tree索引中有一列是由递增的序列号产生的话,那么这些索引信息基本上分布在同一个叶块,当用户修改或访问相似的列时,索引块很容易产生争用。反向索引中的索引码将会被分布到各个索引块中,减少了争用。反向索引反转了索引码中每列的字节,通过dump()函数我们可以清楚得看见它做了什么。举个例子:1,2,3三个连续的数,用dump()函数看它们在Oracle内部的表示方法。 SQL > select ' number ' , dump ( 1 , 16 ) from dual 2 union all select ' number ' ,0);">2 ,0);">3 union all select ' number ' ,0);">3 ,0);">16 ) from dual; ' NUMBE DUMP(1,16) ------ ----------------- number Typ=2 Len=2: c1,2 (1) number Typ=2 Len=2: c1,3 (2) number Typ=2 Len=2: c1,4 (3) 再对比一下反向以后的情况: SQL> select ' number ' ,dump(reverse(1),16) from dual 2 union all select ' ' NUMBE DUMP ( REVERSE ( 1 ),0);">1 -- ---- ----------------- number Typ = 2 Len = 2 : 1 ) 2 ) 4 ,0);">3 )我们发现索引码的结构整个颠倒过来了,这样1,2,3个索引码基本上不会出现在同一个叶块里,所以减少了争用。不过反向索引又一个缺点就是不能在所有使用常规索引的地方使用。在范围搜索中其不能被使用,例如,where column>value,因为在索引的叶块中索引码没有分类,所以不能通过搜索相邻叶块完成区域扫描。 2.3 降序索引 降序索引是8i里面新出现的一种索引,是B*Tree的另一个衍生物,它的变化就是列在索引中的储存方式从升序变成了降序,在某些场合下降序索引将会起作用。举个例子,我们来查询一张表并进行排序: SQL > select * from test where a between 1 and 100 order by a desc ,b asc ; 已选择100行。 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = CHOOSE (Cost = 2 Card = 100 Bytes = 400 ) 1 0 SORT( ORDER BY )(Cost = 2 1 INDEX (RANGE SCAN) OF ' IND_BT ' (NON - UNIQUE ) (Cost = 400 )这里优化器首先选择了一个索引范围扫描,然后还有一个排序的步骤。如果使用了降序索引,排序的过程会被取消。 SQL > create index test.ind_desc on test.testrev(a desc ,b asc ); 索引已创建。 SQL > analyze index test.ind_desc compute statistics ; 索引已分析再来看下执行路径: 100order by a desc ,b asc ; 已选择100行。 Execution Plan (SQL执行计划,稍后会讲解如何使用)。 -- -------------------------------------------------------- 0 INDEX (RANGE SCAN) OF ' IND_DESC ' (NON - UNIQUE ) (Cost = 400 ) 我们看到排序过程消失了,这是因为创建降序索引时Oracle已经把数据都按降序排好了。另外一个需要注意的地方是要设置init.ora里面的compatible参数为8.1.0或以上,否则创建时desc关键字将被忽略。 2.4 位图索引位图索引主要用于决策支持系统或静态数据,不支持行级锁定。位图索引最好用于低cardinality列(即列的唯一值除以行数为一个很小的值,接近零),例如又一个“性别”列,列值有“Male”,“Female”,“Null”等3种,但一共有300万条记录,那么3/3000000约等于0,这种情况下最适合用位图索引。 位图索引可以是简单的(单列)也可以是连接的(多列),但在实践中绝大多数是简单的。在这些列上多位图索引可以与AND或OR操作符结合使用。位图索引使用位图作为键值,对于表中的每一数据行位图包含了TRUE(1)、FALSE(0)、或NULL值。位图索引的位图存放在B-Tree结构的页节点中。B-Tree结构使查找位图非常方便和快速。另外,位图以一种压缩格式存放,因此占用的磁盘空间比B-Tree索引要小得多。 如果搜索where gender=’Male’,要统计性别是”Male”的列行数的话,Oracle很快就能从位图中找到共3行即第1,9,10行是符合条件的;如果要搜索where gender=’Male’ or gender=’Female’的列的行数的话,也很容易从位图中找到共8行即1,2,3,4,7,8,9,10行是符合条件的。如果要搜索表的值的话,那么Oracle会用内部的转换函数将位图中的相关信息转换成rowid来访问数据块。 2.5 函数索引 基于函数的索引也是8i以来的新产物,它有索引计算列的能力,它易于使用并且提供计算好的值,在不修改应用程序的逻辑上提高了查询性能。使用基于函数的索引有几个先决条件: (1)必须拥有QUERY REWRITE(本模式下)或GLOBAL QUERY REWRITE(其他模式下)权限。 QUERY_REWRITE_ENABLED=TRUE 可以通过alter system set,alter session set在系统级或线程级设置,也可以通过在init.ora添加实现。这里举一个基于函数的索引的例子: SQL > create index test.ind_fun on test.testindex( upper (a)); 索引已创建。 SQL > insert into testindex values ( ' a ' , 2 ); 已创建 1 行。 SQL > commit ; 提交完成。 SQL > select /*+ RULE*/ * FROM test.testindex where upper (a) = ' A ' ; A B -- ---------- a 2 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = HINT: RULE 1 0 TABLE ACCESS ( FULL ) OF ' TESTINDEX ' (优化器选择了全表扫描) -- ------------------------------------------------------------------ SQL > select * FROM test.testindex where upper (a) = ' A ' ; A B -- ---------- a 0 SELECT STATEMENT Optimizer = CHOOSE (Cost = 2 Card = 1 Bytes = 5 ) 0 TABLE ACCESS ( BY INDEX ROWID) OF ' TESTINDEX ' (Cost = 2 Card = 2 1 INDEX (RANGE SCAN) OF ' IND_FUN ' (NON - UNIQUE ) (Cost = 1 Car d = 1 )(使用了ind_fun索引)3 各种索引的创建方法 (1)*Tree索引。 4 各种索引使用场合及建议(1)B*Tree索引。 常规索引,多用于oltp系统,快速定位行,应建立于高cardinality列(即列的唯一值除以行数为一个很大的值,存在很少的相同值)。
5 附表(索引什么时候不工作) 首先要声明两个知识点: (1)RBO&CBO。 (2)AUTOTRACE。 Hints是Oracle提供的一个辅助用法,按字面理解就是‘提示’的意思,确实它起得作用也是提示优化器按它所提供的关键字来选择执行路径,特别适用于sql调整的时候。使用方法如下: {DELETE|INSERT|SELECT|UPDATE} /*+ hint [text] [hint[text]]... */ 具体可参考Oracle SQL Reference。有了前面这些知识点,接下来让我们来看一下什么时候索引是不起作用的。以下列出几种情况。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |