oracle b_tree索引、hash索引区别解析

  1. B 树索引(B-Tree索引)

    1. B树索引是我们在oracle数据库中最常用的索引,在详细介绍访问方法之前,我们看一下B-TREE索引的结构(图片来源网络)
               oracle的B树索引就好像一颗长到的树,他包含两种类型,一种是索引分支块(根节点块,分支节点块)一种是索引叶子块(叶子节点块)。分节点用来搜索,叶子节点用来存储数据。根节点存储索引的低层分支节点的数据。 由于所有的叶子节点均会自动的存储成相同的深度,所以称为“平 衡树索引”, 故此,从任何叶子处检索数据消耗的时间都是相同的。
      •   对于分支节点块(包含跟节点块)来说,索引条目(记录)默认按照升序排列可指定为降序。每个索引条目包含两个字段,一个是当前分支节点块中所链接的索引块中包含的最小键值,另一个是链接的索引块地址,指向下一个节点块,长度为4个字节。如上图所示,根节点分别包含(0-B1 500-B2 1000-B3),其中0,500,1000分别表示对应的B1/B2/B3分支节点块键值的最小值,B1/B2/B3指向分支节点块地址。分支节点块中所容纳的记录由数据块大小和索引键值长度决定。分支节点还包含下层叶子节点块的指针。
      • 对于叶子节点来说,包含的索引条目与分支节点一致,默认也是按照升序排列(可指定为降序)。每个索引条目包含2个字段,第一个字段为索引的键值,对于单列索引是一个值,复合索引的值组合在一起;第二个字段为键值对于行的ROWID,即行在表里的物理地址。
        当用户创建索引时,Oracle 取得所有被索引列的数据并进行排序,之后将排序后索引值和与此值相对应的 rowid 按照从下到上的顺序加载到索引中。例如,以下语句:
        CREATE INDEX employees_last_name ON employees(last_name); 

        Oracle先按照last_name排序,再将排序后的列及相应的rowid按照升序加载到索引中,具体使用索引时,可以快速定位到last_name,在根据rowid去查找对于的数据行记录。在一个平衡树索引中,叶子节点块存储被索引的数值,叶子节点块之间以双向链表的形式连接。
        接下来介绍一个索引查询的流程,从上往下,第一层为根节点,第二层为分支节点,第三层为叶子节点(包含了列值和rowid)。比如我们的条件为where=29,(补充说明如果被索引的列存储的是字符数据,那么索引值为这些字符数据在当前数据库字符集中的二进制值)就从跟节点开始查询,29在0-500中,指向分支节点最左边第一个分支节点块(也就是B1),就B1中去找,发现29在0-200中,指向叶子节点的L1,于是在L1中找到29的值和响应的rowid。如果只查找索引列的值,就不用根据rowid去表中查找了,如果还要查找值29这行的其他列的值就得根据rowid去表里查查询(这个过程叫做回表查询)。在通过索引进行范围扫描时会起作用,比如要查找值29-700,如果当查找到值29的时候,不就会再从跟节点开始查找其他的值,而是根据本叶子节点链表的指向去查找其他的值。
          
  2. HASH索引
使用hash索引必须使用hash集群,相当于定义了一个hash集群键,通过这个集群键来告诉oracle来存储表。存储数据时,所有相关集群键的行都存储一个数据库块中,方便快速定位查找。hash索引是一个等值查询,通过hash函数确定行的物理位置。
适用场合:

适合:

  • 精确查找非常快(包括= <> 和in),其检索效率非常高,索引的检索可以一次定位,不像BTree 索引需要从根节点到枝节点,所以 Hash 索引的查询效率要远高于 B-Tree 索引。

不适合:

  • 不适合模糊查询和范围查询(包括like,>,<,between……and等),由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样;
  • 不适合排序,数据库无法利用索引的数据来提升排序性能,同样是因为Hash值的大小不确定;
  • 复合索引不能利用部分索引字段查询,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。
  • 同样不适合键值较少的列(重复值较多的列);
posted @ 2016-10-14 15:56  春风十里的情  阅读(5937)  评论(0编辑  收藏  举报