索引表简介

来源:互联网 发布:淘宝同学课程助手 编辑:程序博客网 时间:2024/06/01 08:57

索引表简介

1、索引的内部构造

因为在索引表中涉及到索引的内部构造知识,所以下面会进行简单的介绍。

首先,如果没有索引,当你想要去查找某个值的时候,你不得不对数据进行顺序扫描,如果一张表有n行,那么使用顺序扫描的平均扫描行数为n/2,一旦表的行数越来越多,这种顺序扫描的效率将大幅下降;如果有索引的参与,使用平衡树扫描的平均扫描行数为log(n),表的行数越多,这种结构带来的扫描效率并不会下降多少。所以Oracle在内部存储索引数据时,使用一种被称为平衡树的结构(B-tree)。如下图所示:

它由两部分组成:

A.      Branch blocks(树枝块):处于最顶层的树枝块又称为根树枝块(root branch blocks);这部分内容在索引一文中再做深入讨论。

B.      LeafBlocks(叶块):处于最底层的块被称为叶块(注意:之所以称为平衡树,是指:平衡树的所有叶块与根树枝块的深度都是一样的);上图是在某表的单列上建立索引;当你建立此索引时,Oracle会自动抓取此列的列值(键值)进行排序;如果是在多列上建立索引呢?Oracle对其排序是按照此列组(属性组)的键值进行排序;因为上图只有一列,那么键值就是其列值。那么,Oracle会把经过排序的列表的值分成(纵向划分)一个一个的区(一个区表示一定宽度的块的范围),这些区以双向链表的结构来组织(所谓双向链表就是一个区带有两个指针,一个指上,一个指下,如上图所示)。你可能会有疑问:那么一个叶块是不是就对应一个数据块呢?答案是否定的!一个叶块不一定就对应一个数据块,有可能一个数据块中有多个叶块,并且这些叶块在物理上不一定就邻接;也有可能某个索引的叶块在这个数据块中,而另一个叶块又在另一个数据块中。如果叶块中的数据是字符数据,那么Oracle还会自动把它们转换为对应的二进制数据(根据所指定的此数据库的字符集设置),所以上图中的叶块数据的格式还不是真正存储在数据库中的数据格式。

2、索引表

索引表使用一种平衡树(B-tree)变体(相对于上节的平衡树)来组织数据的存储(存储结构);而常规的表使用的是(也是一种数据结构)来组织数据的存储(这种数据结构是一种无序的集合)。在这里,所谓平衡树变体结构是指存储在其中的数据需要排序,并且数据的排序是按照主键排序的方式;索引表不仅像索引一样存储主键值(这里的索引指的是在表中的所有列上建立索引),而且在B-tree中的每个索引条目(上节所说的一个叶块)还存有非键值。

图5-9 一个正规表和一个索引表的比较

表5-3索引表和常规表不同的地方

Ordinary Table

Index-Organized Table

Rowid唯一标识一行。主键可指定也可不指定(因为你已经有rowid了)。

由主键来唯一标识一行。主键肯定就必须指定。

使用物理rowid,允许使用它创建二级索引。

使用逻辑rowid,允许使用它创建二级索引。

访问基于物理rowid(使用物理地址)。

访问基于逻辑rowid(使用主键,有可能使用物理猜想)。

返回所有行,使用顺序扫描。

返回所有行,使用全索引扫描。

能被存储在一个簇中。

不能被存储在一个簇中。

一列中能够含有数据类型为LONG、LOB的数据。

能含有LOB数据类型,但不能有LONG数据类型

 

小结:

如果有一张常规表,在它的所有列上创建一个索引,那么这张表和在这张表上的索引的组合就有点类似于索引表;不过,这个索引并不一定就拥有这张表所有的键值,因为这时索引的规范是:在同一个数据块中的键值只要能够被区分,那么就不必要整个键值都做存储,而只要存储键值的一部分;而索引表是存储了表中的所有键值;不过,索引表的想法就是由此开始的(因为它能提供最快速的访问)。

常规表和其索引是两个独立的存储结构,而索引表是一个单一的存储结构;

索引表的平衡树(B-tree)存储结构的条目是由<primary_Key_value,

non_primary_key_column_values>值对组成(它是使用逻辑rowids);而常规表索引的平衡树(B-tree)存储结构的条目是由<Key_value,rowid>值对组成(它是使用物理rowids)。

应用程序可以像使用常规表一样使用索引表(使用SQL语句);只不过,对索引表的操作是数据库系统内部通过操作相对应的B-tree数据结构索引来完成的。

2.1溢出(Overflow)

平衡树式的索引条目(入口)通常很小,因为对于常规表的索引来说,它们的条目仅仅包含<键值,rowid>对(在上一节总结中所举的例子是一种极端情况,只是用来理解)。然而对于索引来说,它的入口条目就比较大了,因为它必须包含整一个的行(不管你是键值还是非键值,你都得储存);这样就很有可能摧毁密集簇的平衡树索引。

Oracle提供OVERFLOW字句来处理这个问题。你能指定一个overflow表空间,如果必要,你还能把一行分成以下两个部分(一部分存储在索引中,而另一部分就存储在overflow段中):

·        索引条目包含:主键列中的主键值、一个物理rowid(也就是一个指向行溢出部分的指针)和一部分可选的非键列的值。

·        overflow部分包含:剩余的非键值。

OVERFLOW又有两个字句:PCTTHRESHOLD(阈值百分比)和INCLUDING

使用PCTTHRESHOLD你能提供一个以百分比来表示的阈值(对块的大小进行限制);如果非键列值超过了这个限制值,那么第一个非键列的值和之后的所有非键列的值都将存储在overflow段。

INCLUDING字句是让你指定某列的列名,这个列名是任意的非键列的列名,此列是出现在CREATETABLE语句的指定列表中的列,它/它们仍然被存储在行溢出段中。不过,其它的非键列(不在INCLUDING字句中的非键列),也要遵从PCTTHRESHOLD的设置。下面是个例子:

CREATE TABLE admin_docindex2(
        token CHAR(20), 
        doc_id NUMBER,
        token_frequency NUMBER,
        token_offsets VARCHAR2(512),
        CONSTRAINT pk_admin_docindex2 PRIMARY KEY (token, doc_id))
    ORGANIZATION INDEX 
    TABLESPACE admin_tbs
    PCTTHRESHOLD 20
    INCLUDING token_frequency
OVERFLOW TABLESPACE admin_tbs2;
 
2.2二级索引(辅助索引)

索引表上的二级索引能够非常有效地访问索引表,这种索引既不是使用主键列也不是使用主键的某个前缀。Oracle构造这种索引使用的是逻辑的行标识符(logicalrowids),这种rowids是基于表的主键(而不是基于行的物理地址)。这种逻辑rowids包括了一个物理猜想(physical guess),它也是一种物理标识符(物理指针),它唯一标识行的块地址,Oracle能使用这些猜想直接对索引表的叶块进行探测,从而避免主键搜索。不过,在rowids一文中也讲过,由于索引表不拥有永久/不变的物理地址,索引这种物理猜想可能会变得陈旧/无效。

对一个常规表来说,通过一个二级索引进行访问会卷入对二级索引的一次扫描以及一个额外的I/O操作(抓取包含有目标行的数据块);对于索引表来说,通过一个二级索引的变体进行访问依赖于如何使用以及精准的物理猜想:

·        如果没有使用物理猜想,那么访问涉及到两个索引扫描:1、一次二级索引扫描2、紧随其后的一次主键索引扫描

·        如果使用有效的(精准的)物理猜想,那么访问涉及到一次二级索引扫描和一个额外的I/O操作(抓取包含有目标行的数据块,直接定位到了包含此行的数据块)

·        如果使用过期的物理猜想,呢么访问涉及到一次二级索引扫描和一个I/O操作,只不过所抓取到的数据块是错误的,紧随其后的是不得不进行一次主键索引扫描。

2.3索引表上的位图(Bitmap)索引

Oracle支持在被分割或未被分割的索引表上使用位图(bitmap)索引,创建位图索引时需要一张映射表。

2.3.1映射表(Mapping Table)

映射(mapping)表是也是一种堆组织结构的表,它存储着索引表的逻辑rowids,更进一步说,每张映射表的一行存储了索引表的一个逻辑rowids(这个rowids唯一标识索引表的一行)。因此,映射表提供了逻辑rowids和其索引表中的行的一一对应关系,并且这种映射表同样拥有物理rowids。

建立在索引表上的一个位图索引和建立在堆组织结构表上的位图索引很类似,不同的是,前者的位图索引使用的rowids是映射表中的rowids,而不是基表的。每个索引表可以拥有一张映射表,而某个索引表的所有位图都将使用一张映射表。

不管是堆表还是索引表,访问一个位图索引都是使用某个搜索键。如果这个搜索键被找到,那么根据位图的入口条目就可以找到一个物理rowid。对于堆表来说,这个物理rowid是被用来访问其基表的;而对于索引表来说,这个物理rowid是用来访问映射表的,而从索引表又可以获得一个逻辑rowid,这个逻辑rowid又是用来访问索引表的。

通过位图索引好像不会存储逻辑rowids,不过从上面可以看出,这种索引本质还是逻辑的。

注意:

行的移动不会造成位图的失效;但是,行的移动会造成映射表中的逻辑rowid中的物理猜想失效,不过索引表仍然能使用主键进行访问。

 

 

 

2.4分割索引表

你能通过在列值上使用RANGEHASHLIST分割一个索引表。这部分内容在分割一文中再做深入讨论。

2.5堆表和索引表中的UROWID类型列上的平衡树索引

数据类型为UROWID的列也可用于存储根据基于主键的逻辑rowid。Oracle支持在堆表或索引表的UROWID列上创建索引;但是只有当一个查询中谓词的条件为“等于”时,Oracle才会使用此索引,“等于”之外的谓词条件及对此列进行排序都不会使用此索引。

2.6索引表的应用

索引表可应用在以下情况:

·        联机事务处理(OLTP)

·        Internet (例如:搜索引擎和门户网络)

·        电子商务 (例如:电子商店和购物目录)

·        数据仓库

·        分析应用

 

原创粉丝点击