内容


通过 oncheck 理解 Informix 索引结构

Comments

引言

在 Informix 中,可以通过索引来快速定位“需要使用的数据行”。那么一般的 Informix 索引是通过什么结构来实现“快速定位数据行”的目的呢?本文将通过 oncheck 命令来展示实际的 Informix 索引结构,为您揭晓这个问题的答案。

Informix 索引简介

在 Informix 中,一个数据表里可能有很多数据行(row)。例如某连锁超市的“客户基本信息”数据表里有 7 百万个数据行(即 7 百万个客户的基本信息)。Informix 收到超市工作人员输入的“某个客户的客户号”后,需要快速的向超市工作人员返回“这个客户的姓名、邮箱、住址等信息”。如果 Informix 收到“某个客户的客户号”后,把“客户基本信息”数据表的 7 百万个数据行从前往后一行一行顺序扫描,那么 Informix 将无法快速返回结果。如何才能达到“快速返回结果”的目的呢?答案是使用 Informix 索引。Informix 索引就像是中文字典里的拼音目录。拼音目录里记录了每个拼音和对应的页码,Informix 索引里记录了每个特征值(例如每个客户的客户号)和对应的数据行地址。通过拼音目录可以快速的得到某个拼音对应的页码,通过 Informix 索引可以快速的得到某个特征值(例如某个客户的客户号)对应的数据行地址。

在 Informix 中一般的索引是通过 B+ 树这种数据结构来实现的。B+ 树是一种树结构,它的每个节点可以有多个分叉。B+ 树可以是 1 层或多层。在 B+ 树中,所有的叶节点都在同一层,即不会出现类似这样的情况:在一棵 B+ 树中,有的叶节点在第 2 层,有的叶节点在第 3 层。关于 B+ 树的详细叙述请参看 Wikipedia 上关于 B+ 树的内容。B+ 树的结构如图 1 所示。

图 1. 图 1. B+ 树的结构
B+ 树的结构
B+ 树的结构

图 1 中的 B+ 树一共有 3 层:第 1 层是根节点,第 2 层是分支节点,第 3 层是叶节点。节点里有多个节点项 (entry),每个节点项由键 (key) 和值 (value) 组成。节点项的键一般为整数、字符串或“ ‘元素是整数或字符串’ 的集合”。在图 1 的节点中,节点项的键为整数。节点项的值 (value) 一般为指针。在非叶节点中,节点项的值指向子节点。在叶节点中,节点项的值为空指针或指向具体数据的指针。在图 1 的叶节点中,节点项的值指向数据行。一般情况下,每个节点还有两个指针,分别指向“前一个兄弟节点”和“后一个兄弟节点”。

Informix 索引对应的 B+ 树一般是 2 层、3 层或 4 层。

在 Informix 索引对应的 B+ 树中,1 个节点是 1 个页 (page)。

oncheck 命令的简介

在 Informix 中,oncheck 命令可以检查和打印数据对象。例如:

  1. oncheck -cr 可以检查数据库保留页的正确性
  2. oncheck -cD <databaseName>:<tableName> 可以检查数据的正确性
  3. oncheck -cI <databaseName>:<tableName>#<indexName> 可以检查索引的正确性
  4. oncheck -pe <dbsName> 可以打印某个 dbspace 中所有 extent 的分布情况
  5. oncheck -pP <chunkNum> <startPageNum> <numOfPages> 可以打印指定的数据页
  6. oncheck -pT <databaseName>:<tableName> 可以打印“某个数据表以及其上的索引”的磁盘使用情况

关于 oncheck 命令的详细叙述请参看 Informix Information Center 中关于 oncheck 的内容

准备工作

本文通过一个例子来讲述“如何通过 oncheck 命令来展示 Informix 索引结构”。通过以下步骤来创建这个例子所需的数据对象:

(1)首先通过如下的 SQL 语句在名为 dbs1 的 dbspace 中创建数据库 db1:

                    create database db1 in dbs1 with log;

(2)然后使用如下的 SQL 语句在 db1 中创建数据表、加载数据、创建索引:

 create table employee ( 
  employeenum int, 
  deptnum int, 
  profnum int, 
  band int, 
  name char(10), 
  description varchar(200) 
 ); 

 create procedure employeeProc()                                      
 define my_employeenum integer; 
 define my_deptnum integer; 
 define my_profnum integer; 
 define my_band integer; 
 define my_name char(10); 
 define my_description varchar(200); 

 let my_profnum = 1; 
 let my_band = 0; 

 for my_employeenum = 1 to 60000 

 let my_deptnum = my_employeenum / 5 + 1; 

 let my_band = my_band + 1; 
 if (my_band = 51) then 
  let my_band = 1; 
  let my_profnum = my_profnum + 1; 
 end if; 

 let my_name = 'name' || my_employeenum; 
 let my_description = 'Description of employee ' || my_employeenum || 
                     ': she/he is an excellent employee.'; 

 insert into employee values 
 (my_employeenum, my_deptnum, my_profnum, my_band, my_name, my_description); 

 end for; 

 end procedure; 

 call employeeProc(); 

 create unique index idx1 on employee ( employeenum ); 
 create index idx2 on employee ( deptnum ); 
 create unique index idx3 on employee ( profnum, band );

上面的 SQL 语句创建了名为 employee 的数据表,该数据表有 6 个数据列:employeenum 是员工号,deptnum 是部门号,profnum 是职业种类号,band 是职业等级,name 是员工姓名,description 是对员工的描述。上面的 SQL 语句使用存储过程 employeeProc 往数据表 employee 中插入了 60000 行实验数据。这 60000 行实验数据如表 1 所示。

表 1. 表1. 数据表 employee 中的数据的示例
employeenumdeptnumprofnumbandnamedescription
1111name1Description of employee 1: she/he is an excellent employee.
2112name2Description of employee 2: she/he is an excellent employee.
3113name3Description of employee 3: she/he is an excellent employee.
4114name4Description of employee 4: she/he is an excellent employee.
5215name5Description of employee 5: she/he is an excellent employee.
6216name6Description of employee 6: she/he is an excellent employee.
............... ...... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
6000012001120050name60000Description of employee 60000: she/he is an excellent employee.

(若要查看全部 60000 行实验数据,请参看文件 employee.txt。文件 employee.txt 被包含在附件“Informix 索引结构 .zip”中。)

在数据表 employee 上有 3 个索引:idx1、idx2、idx3。idx1 是单列唯一索引(single-column unique index)。idx2 是单列非唯一索引(single-column non-unique index)。idx3 是多列唯一索引(multi-column unique index)。“单列”意味着索引是建在 1 个数据列上。“多列”意味着索引是建在多个数据列上。“唯一”是指任意两个数据行的索引键不能相同,例如对于唯一索引 idx1,任意两个数据行的 employeenum 不能相同。“非唯一”是指两个数据行的索引键可以相同。

单列唯一索引的结构

我们先来关注单列唯一索引 idx1。如何查看 idx1 的内部结构呢?答案是使用 oncheck 命令。我们使用 oncheck -pT 来查看 idx1 的层次,使用 oncheck -pP 来查看 idx1 的所有节点的内容,具体操作如下(这些 oncheck 命令的语法请参看前文的“oncheck 命令的简介”这一章):

  1. 使用如下命令将“数据表 employee 以及其上的索引”的磁盘使用情况输出到文件 pT.out 中:
                        oncheck -pT db1:employee > pT.out

    (文件 pT.out 被包含在附件“Informix 索引结构 .zip”中)

  2. 使用如下命令将 dbs1(dbs1 是“employee、idx1、idx2、idx3”所在的 dbspace)中所有 extent 的信息输出到文件 pe.out 中:
                        oncheck -pe dbs1 > pe.out

    (文件 pe.out 被包含在附件“Informix 索引结构 .zip”中)

  3. 在文件 pe.out 中,可以看到如下信息:
     ... ... 
     ... ... 
     Chunk  Pathname                        Pagesize(k)  Size(p)  Used(p)  Free(p) 
     10     /opt/ts/dbs/dbs1                     2       500000   6015     493985 
    
     Description                                                   Offset(p)  Size(p) 
     ... ... 
     ... ...   
     db1:'informix'.idx1                                               4607     512 
     ... ... 
     ... ...

    这说明索引 idx1 由一个 extent 组成 ( 一个 extent 是一组物理上连续的页 ),idx1 所在的 chunk 的 chunk 号是 10,idx1 的起始页在 chunk 内的页地址为 4607,idx1 的总页数为 512。(chunk 号和 chunk 内的页地址组成物理页地址,所以 idx1 的起始页的物理页地址是 10:4607。)于是我们使用如下命令将 idx1 的内容输出到文件 idx1.out 中:

                  oncheck -pP 10 4607 512 > idx1.out

    (文件 idx1.out 被包含在附件“Informix 索引结构 .zip”中)

idx1 的层次

从 pT.out 文件中,我们可以看到 idx1 的层次结构如下:

                    Average    Average 
    Level    Total No. Keys Free Bytes 
    ----- -------- -------- ---------- 
        1        1        3       1988 
        2        3      144        293 
        3      432      138        214 
    ----- -------- -------- ---------- 
    Total      436      138        219

idx1 共有 3 层:第 1 层有 1 个节点,该节点是 idx1 的根节点,该节点有 3 个索引项;第 2 层有 3 个节点,这些节点是 idx1 的分支节点,平均每个分支节点有 144 个索引项;第 3 层有 432 个节点,这些节点是 idx1 的叶节点,平均每个叶节点有 138 个索引项。

idx1 的根节点

在文件 idx1.out 中一共有 512 个页。其中哪一页是 idx1 的根节点呢?

在索引中,逻辑页地址为 0 的页(即起始页)是空白页,逻辑页地址为 1 的页是根节点。(一个页的逻辑页地址表示:从起始页(即第 0 页)算起,该页在逻辑上是第几页。)

如果 idx1 由一个 extent 组成 ( 一个 extent 是一组物理上连续的页 ),那么“页地址转换公式”如下:

当 1 个索引是由 1 个 extent 组成时的页地址转换公式:
    索引节点的物理页地址 = 索引的起始页的物理页地址 + 索引节点的逻辑页地址

由于 idx1 的起始页的物理页地址为 10:4607(请参看本章“单列唯一索引的结构”的开头部分),idx1 的根节点的逻辑页地址为 1,所以 idx1 的根节点的物理页地址为 10:4608。

在文件 idx1.out 中,可以看到物理页地址为 10:4608 的页(即 idx1 的根节点)的内容如图 2 所示。

图 2. 图 2. idx1 的根节点的内容
idx1 的根节点的内容
idx1 的根节点的内容

在图 2 中,1 个 slot 是 1 个索引项。idx1 的根节点有 3 个 slot,因此 idx1 的根节点有 3 个索引项。第 1 个索引项的键 (key) 为 0x51fd,值 (value) 为 0x3,这说明“第 1 个索引项指向的索引页”的逻辑页地址为 0x3,也就是说“根节点的第 1 个子节点”的逻辑页地址为 0x3。第 2 个索引项的键 (key) 为 0xa3fa,值 (value) 为 0x9c,这说明“第 2 个索引项指向的索引页”的逻辑页地址为 0x9c,也就是说“根节点的第 2 个子节点”的逻辑页地址为 0x9c。第 3 个索引项由于是根节点的最后一个索引项,所以没有键 (key),只有值 (value)。第 3 个索引项的值 (value) 为 0x134,这说明“第 3 个索引项指向的索引页”的逻辑页地址为 0x134,也就是说“根节点的第 3 个子节点”的逻辑页地址为 0x134。

在图 2 的右上部分,可以看到 next 和 prev。next 表示后一个兄弟节点的逻辑页地址,next 的值为 0 表示没有后一个兄弟节点;prev 表示前一个兄弟节点的逻辑页地址,prev 的值为 0 表示没有前一个兄弟节点。由于根节点没有兄弟节点,所以在根节点中 next 的值和 prev 的值都为 0。

idx1 的分支节点

在 idx1 的第 2 层有 3 个分支节点。这 3 个分支节点是 idx1 的根节点的子节点。

下面我们以 idx1 的第 1 个分支节点(即根节点的第 1 个子节点,为叙述方便,下文简称为分支节点 B)为例来讲述 idx1 的分支节点。

在上一节中,我们已经知道分支节点 B(即根节点的第 1 个子节点)的逻辑页地址为 0x3,根据上一节提到的“页地址转换公式”,可以得知分支节点 B 的物理页地址为 10:4610。

在文件 idx1.out 中,可以看到物理页地址为 10:4610 的页(即分支节点 B)的内容如下所示:

 addr             stamp    chksum nslots flag type         frptr frcnt next     prev 
 10:4610          110571078 3ad9   151    850  BTREE        1232  208   9c       0     
	 slot ptr   len   flg 
	 1    24    8     0  
	 2    32    8     0  
	 3    40    8     0  
	 4    48    8     0  
	 5    56    8     0  
	 6    64    8     0  
	 7    72    8     0 
	 ... ... 
	 ... ... 
	 150  1216  8     0  
	 151  1224  8     0  
 slot   1: 
    0: 80  0  0 8b  0  0  0  2                           ................ 
 slot   2: 
    0: 80  0  1 16  0  0  0  4                           ................ 
 slot   3: 
    0: 80  0  1 a1  0  0  0  5                           ...!............ 
 slot   4: 
    0: 80  0  2 2c  0  0  0  6                           ...,............ 
 slot   5: 
    0: 80  0  2 b7  0  0  0  7                           ...7............ 
 slot   6: 
    0: 80  0  3 42  0  0  0  8                           ...B............ 
 slot   7: 
    0: 80  0  3 cd  0  0  0  9                           ...M............ 
 ... ... 
 ... ... 
 slot 150: 
    0: 80  0 51 72  0  0  0 98                           ..Qr............ 
 slot 151: 
    0: 80  0 51 fd  0  0  0 99                           ..Q}............

从上面的分支节点 B 的内容中,可以看到分支节点 B 一共有 151 个索引项(即 151 个 slot)。每个索引项都有键 (key) 和值 (value),索引项的值指向一个叶节点。例如:第 1 个索引项的键 (key) 为 0x8b,值 (value) 为 0x2,这说明“第 1 个索引项指向的索引页”的逻辑页地址为 0x2,也就是说“分支节点 B 的第 1 个子节点”的逻辑页地址为 0x2;第 151 个索引项的键 (key) 为 0x51fd,值 (value) 为 0x99,这说明“第 151 个索引项指向的索引页”的逻辑页地址为 0x99,也就是说“分支节点 B 的第 151 个子节点”的逻辑页地址为 0x99。

从上面的分支节点 B 的内容中,还可以看到:next 的值为 9c,prev 的值为 0。这表明分支节点 B 的下一个兄弟节点的逻辑页地址为 0x9c,分支节点 B 没有上一个兄弟节点。

“idx1 的其它分支节点”与分支节点 B 的结构相同。

idx1 的叶节点

在 idx1 的第 3 层有 432 个叶节点。这 432 个叶节点是 idx1 的分支节点的子节点。

下面我们以 idx1 的第 1 个叶节点(即分支节点 B 的第 1 个子节点,为叙述方便,下文简称为叶节点 L)为例来讲述 idx1 的叶节点。

在上一节中,我们已经知道叶节点 L(即分支节点 B 的第 1 个子节点)的逻辑页地址为 0x2,根据“idx1 的根节点”这一节提到的“页地址转换公式”,可以得知叶节点 L 的物理页地址为 10:4609。

在文件 idx1.out 中,可以看到物理页地址为 10:4609 的页(即叶节点 L)的内容如下所示:

 addr             stamp    chksum nslots flag type         frptr frcnt next     prev 
 10:4609          110570306 3fde   139    890  BTREE        1275  213   4        0     
	 slot ptr   len   flg 
	 1    24    9     0  
	 2    33    9     0  
	 3    42    9     0  
	 4    51    9     0  
	 5    60    9     0  
	 6    69    9     0  
	 7    78    9     0 
	 ... ... 
	 ... ... 
	 138  1257  9     0  
	 139  1266  9     0  
 slot   1: 
    0: 80  0  0  1  0  0  1  1  0                        ................ 
 slot   2: 
    0: 80  0  0  2  0  0  1  2  0                        ................ 
 slot   3: 
    0: 80  0  0  3  0  0  1  3  0                        ................ 
 slot   4: 
    0: 80  0  0  4  0  0  1  4  0                        ................ 
 slot   5: 
    0: 80  0  0  5  0  0  1  5  0                        ................ 
 slot   6: 
    0: 80  0  0  6  0  0  1  6  0                        ................ 
 slot   7: 
    0: 80  0  0  7  0  0  1  7  0                        ................ 
 ... ... 
 ... ... 
 slot 138: 
    0: 80  0  0 8a  0  0  7 12  0                        ................ 
 slot 139: 
    0: 80  0  0 8b  0  0  7 13  0                        ................

从上面的叶节点 L 的内容中,可以看到叶节点 L 一共有 139 个索引项(即 139 个 slot)。每个索引项都有键 (key) 和值 (value),索引项的值指向一个数据行。例如:第 1 个索引项的键 (key) 为 0x1,值 (value) 为 0x101,这说明“第 1 个索引项指向的数据行”的 ROWID(数据行 ID)为 0x101;第 139 个索引项的键 (key) 为 0x8b,值 (value) 为 0x713,这说明“第 139 个索引项指向的数据行”的 ROWID(数据行 ID)为 0x713。

从上面的叶节点 L 的内容中,还可以看到:next 的值为 4,prev 的值为 0。这表明叶节点 L 的下一个兄弟节点的逻辑页地址为 0x4,叶节点 L 没有上一个兄弟节点。

“idx1 的其它叶节点”与叶节点 L 的结构相同。

idx1 结构的示意图

根据 idx1 的各节点的内容,可以得出 idx1 的结构如图 3 所示。

图 3. 图 3. 单列唯一索引 idx1 的结构
单列唯一索引 idx1 的结构
单列唯一索引 idx1 的结构

单列非唯一索引的结构

单列非唯一索引和单列唯一索引在内部结构上的区别主要是叶节点:在单列非唯一索引的叶节点中,每个索引项包含 1 个键 (key) 和“1 或多个值 (value)”;在单列唯一索引的叶节点中,每个索引项包含 1 个键 (key) 和“1 个值 (value)”。

下面以“单列非唯一索引 idx2 的第 1 个叶节点”为例来说明单列非唯一索引的叶节点。

idx2 的第 1 个叶节点的内容如下(获取“idx2 的第 1 个叶节点的内容”的过程与获取“idx1 的第 1 个叶节点的内容”的过程相似):

 addr             stamp    chksum nslots flag type         frptr frcnt next     prev 
 10:5121          110573127 24db   55     890  BTREE        1614  210   4        0       
	 slot ptr   len   flg 
	 1    24    24    0  
	 2    48    29    0  
	 3    77    29    0  
	 4    106   29    0  
	 5    135   29    0  
	 6    164   29    0  
	 7    193   29    0 
	 ... ...     
	 ... ... 
	 54   1556  29    0  
	 55   1585  29    0  
 slot   1: 
    0: 80  0  0  1  0  0  1  1  0  0  0  1  2  0  0  0   ................ 
   16:  1  3  0  0  0  1  4  0                           ................ 
 slot   2: 
    0: 80  0  0  2  0  0  1  5  0  0  0  1  6  0  0  0   ................ 
   16:  1  7  0  0  0  1  8  0  0  0  1  9  0            ................ 
 slot   3: 
    0: 80  0  0  3  0  0  1  a  0  0  0  1  b  0  0  0   ................ 
   16:  1  c  0  0  0  1  d  0  0  0  1  e  0            ................ 
 slot   4: 
    0: 80  0  0  4  0  0  1  f  0  0  0  1 10  0  0  0   ................ 
   16:  1 11  0  0  0  1 12  0  0  0  1 13  0            ................ 
 slot   5: 
    0: 80  0  0  5  0  0  1 14  0  0  0  2  1  0  0  0   ................ 
   16:  2  2  0  0  0  2  3  0  0  0  2  4  0            ................ 
 slot   6: 
    0: 80  0  0  6  0  0  2  5  0  0  0  2  6  0  0  0   ................ 
   16:  2  7  0  0  0  2  8  0  0  0  2  9  0            ................ 
 slot   7: 
    0: 80  0  0  7  0  0  2  a  0  0  0  2  b  0  0  0   ................ 
   16:  2  c  0  0  0  2  d  0  0  0  2  e  0            ................ 
 ... ... 
 ... ... 
 slot  54: 
    0: 80  0  0 36  0  0  e  5  0  0  0  e  6  0  0  0   ...6............ 
   16:  e  7  0  0  0  e  8  0  0  0  e  9  0            ................ 
 slot  55: 
    0: 80  0  0 37  0  0  e  a  0  0  0  e  b  0  0  0   ...7............ 
   16:  e  c  0  0  0  e  d  0  0  0  e  e  0            ................

从 idx2 的第 1 个叶节点的内容中,可以看到该叶节点一共有 55 个索引项。每个索引项都有 1 个键 (key) 和多个值 (value)。例如:第 1 个索引项的键 (key) 为 0x1,多个值 (value) 分别为 0x101、0x102、0x103、0x104,这说明“第 1 个索引项”指向 4 个数据行,这 4 个数据行的 ROWID(数据行 ID)分别为 0x101、0x102、0x103、0x104;第 55 个索引项的键 (key) 为 0x37,多个值 (value) 分别为 0xe0a、0xe0b、0xe0c、0xe0d、0xe0e,这说明“第 55 个索引项”指向 5 个数据行,这 5 个数据行的 ROWID(数据行 ID)分别为 0xe0a、0xe0b、0xe0c、0xe0d、0xe0e。

idx2 的其它节点的内容请参看文件 idx2.out(文件 idx2.out 被包含在附件“Informix 索引结构 .zip”中)。

根据 idx2 的各节点的内容,可以得出 idx2 的结构如图 4 所示。

图 4. 图 4. 单列非唯一索引 idx2 的结构
单列非唯一索引 idx2 的结构
单列非唯一索引 idx2 的结构

多列唯一索引的结构

多列唯一索引和单列唯一索引在内部结构上的区别主要是:在多列唯一索引的节点中,索引项的键 (key) 由多个数据列构成;在单列唯一索引的节点中,索引项的键 (key) 由 1 个数据列构成。

下面以“多列唯一索引 idx3 的第 1 个叶节点”为例来说明多列唯一索引的节点。

idx3 的第 1 个叶节点的内容如下(获取“idx3 的第 1 个叶节点的内容”的过程与获取“idx1 的第 1 个叶节点的内容”的过程相似):

 addr             stamp    chksum nslots flag type         frptr frcnt next     prev 
 10:5377          110574370 28be   106    890  BTREE        1402  218   4        0       
	 slot ptr   len   flg 
	 1    24    13    0  
	 2    37    13    0  
	 3    50    13    0  
	 4    63    13    0  
	 5    76    13    0  
	 6    89    13    0  
	 7    102   13    0  
	 ... ... 
	 ... ... 
	 105  1376  13    0  
	 106  1389  13    0  
 slot   1: 
    0: 80  0  0  1 80  0  0  1  0  0  1  1  0            ................ 
 slot   2: 
    0: 80  0  0  1 80  0  0  2  0  0  1  2  0            ................ 
 slot   3: 
    0: 80  0  0  1 80  0  0  3  0  0  1  3  0            ................ 
 slot   4: 
    0: 80  0  0  1 80  0  0  4  0  0  1  4  0            ................ 
 slot   5: 
    0: 80  0  0  1 80  0  0  5  0  0  1  5  0            ................ 
 slot   6: 
    0: 80  0  0  1 80  0  0  6  0  0  1  6  0            ................ 
 slot   7: 
    0: 80  0  0  1 80  0  0  7  0  0  1  7  0            ................ 
 ... ... 
 ... ... 
 slot 105: 
    0: 80  0  0  3 80  0  0  5  0  0  6  5  0            ................ 
 slot 106: 
    0: 80  0  0  3 80  0  0  6  0  0  6  6  0            ................

从 idx3 的第 1 个叶节点的内容中,可以看到该叶节点一共有 106 个索引项。每个索引项都有 1 个键 (key) 和 1 个值 (value),索引项的键由两个数据列构成。例如:第 1 个索引项的键 (key) 为(0x1,0x1),值 (value) 为 0x101;第 106 个索引项的键 (key) 为(0x3,0x6),值 (value) 为 0x606。

idx3 的其它节点的内容请参看文件 idx3.out(文件 idx3.out 被包含在附件“Informix 索引结构 .zip”中)。

根据 idx3 的各节点的内容,可以得出 idx3 的结构如图 5 所示。

图 5. 图 5. 多列唯一索引 idx3 的结构
多列唯一索引 idx3 的结构
多列唯一索引 idx3 的结构

3 种 Informix 索引在内部结构上的特点

从前面的叙述中,可以知道 3 种 Informix 索引在内部结构上的特点如表 2 所示。

表 2. 表 2. 3 种 Informix 索引在内部结构上的特点
索引种类特点
单列唯一索引在节点中,索引项的键 (key) 由 1 个数据列构成 ;
在节点中,每个索引项有 1 个值 (value)。
单列非唯一索引在节点中,索引项的键 (key) 由 1 个数据列构成;
在非叶节点中,每个索引项有 1 个值 (value);
在叶节点中,每个索引项有 1 个或多个值 (value)。
多列唯一索引在节点中,索引项的键 (key) 由多个数据列构成;
在节点中,每个索引项有 1 个值 (value)。

一些说明

下面是对本文的一些说明:

  1. 在本文叙述的索引中,索引项都是不跨页的。索引项跨页(即索引项 E 的一部分在页 P1,索引项 E 的另一部分在页 P2 上)的情况较少,也较复杂,不在本文的叙述范围内。
  2. 多列非唯一索引兼具“多列”和“非唯一”的特点:在节点中,索引项的键 (key) 由多个数据列构成;在非叶节点中,每个索引项有 1 个值 (value); 在叶节点中,每个索引项有 1 个或多个值 (value)。由于篇幅限制,本文不对“多列非唯一索引”进行详细叙述。
  3. 1 个索引在物理存储上可以由 1 个或多个 extent 组成。extent 的个数不影响索引的逻辑结构。为使叙述更加简明,本文叙述的每个示例索引在物理存储上都由 1 个 extent 组成。
  4. 在一般的索引中,1 个索引只有 1 个根节点。在 Informix 11.70 中新推出的 Forest-Of-Trees 类型的索引中,1 个索引可以有多个根节点。
  5. 在一般的索引中,Informix 使用 B+ 树作为索引的内部结构。在一些特殊的索引中,Informix 可能使用其它数据结构作为索引的内部结构。例如在处理空间数据 (spatial data) 时,Informix 使用了 R-Tree 作为索引的内部结构。这些特殊的索引结构不在本文的叙述范围内。

结束语

本文叙述了 3 种 Informix 索引的内部结构,使读者对 Informix 索引的层次、根节点、分支节点、叶节点等有较深的理解。

读者理解 Informix 索引的内部结构后,可以更好的设计 Informix 索引,较大的提升 Informix 数据库和 Informix 应用程序的性能。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management
ArticleID=832485
ArticleTitle=通过 oncheck 理解 Informix 索引结构
publish-date=08302012