ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 索引组织表上创建BITMAP索引(二)

索引组织表上创建BITMAP索引(二)

原创 Linux操作系统 作者:yangtingkun 时间:2010-08-11 23:30:36 0 删除 编辑

Oracle的索引组织表也支持BITMAP索引类型,不过需要映射表的支持。

描述一下映射表的结构的特点。

索引组织表上创建BITMAP索引(一):http://yangtingkun.itpub.net/post/468/503513

 

 

上一篇文章介绍了索引组织表的映射表,下面简单描述一下映射表的结构,以及为什么Oracle需要这个映射表。

SQL> DROP TABLE T_INDEX_ORG;

表已删除。

SQL> CREATE TABLE T_INDEX_ORG
  2  (ID NUMBER PRIMARY KEY,
  3  NAME VARCHAR2(30),
  4  TYPE VARCHAR2(30))
  5  ORGANIZATION INDEX
  6  MAPPING TABLE;

表已创建。

SQL> CREATE BITMAP INDEX IND_B_INDEX_TYPE
  2  ON T_INDEX_ORG (TYPE);

索引已创建。

SQL> SELECT TABLE_NAME, IOT_NAME, IOT_TYPE
  2  FROM USER_TABLES
  3  WHERE IOT_TYPE IS NOT NULL;

TABLE_NAME                     IOT_NAME                       IOT_TYPE
------------------------------ ------------------------------ ------------
SYS_IOT_MAP_32399              T_INDEX_ORG                    IOT_MAPPING
T_INDEX_ORG                                                   IOT

SQL> SELECT TABLE_NAME, INDEX_NAME, INDEX_TYPE
  2  FROM USER_INDEXES
  3  WHERE TABLE_NAME = 'T_INDEX_ORG';

TABLE_NAME                     INDEX_NAME                     INDEX_TYPE
------------------------------ ------------------------------ -------------
T_INDEX_ORG                    SYS_IOT_TOP_32399              IOT - TOP
T_INDEX_ORG                    IND_B_INDEX_TYPE               BITMAP

现在已经建立好索引组织表、映射表和BITMAP索引,首先来看看映射表的结构:

SQL> DESC SYS_IOT_MAP_32399
 
名称                                                              是否为空? 类型
 ----------------------------------------------------------------- -------- --------------
 SYS_NC_01                                                                  ROWID

映射表的结构很简单,只有一个ROWID字段。

下面在表中插入一条记录:

SQL> INSERT INTO T_INDEX_ORG VALUES (1, 'T_INDEX_ORG', 'IOT');

已创建 1 行。

可以看到,映射表中自动包含了ROWID信息。

SQL> SELECT * FROM SYS_IOT_MAP_32399;

SYS_NC_01
--------------------------------------------------
*BAAAAAACwQL+

根据这个ROWID,就可以从索引组织表找到对应的记录:

SQL> SELECT * FROM T_INDEX_ORG
  2  WHERE ROWID = '*BAAAAAACwQL+';

        ID NAME                           TYPE
---------- ------------------------------ ------------
         1 T_INDEX_ORG                    IOT

但是仔细观察一下,就会发现映射表中的ROWID与从索引组织表中查询得到的ROWID并不相同:

SQL> SELECT ROWID FROM T_INDEX_ORG;

ROWID
-------------------------------------
*BAJAADQCwQL+

通过DUMP看看二者的差别:

SQL> COL D_ROWID FORMAT A50
SQL> SELECT ROWID, DUMP(ROWID, 16) D_ROWID
  2  FROM T_INDEX_ORG;

ROWID                           D_ROWID
------------------------------- ------------------------------------------------
*BAJAADQCwQL+                   Typ=208 Len=10: 2,4,2,40,0,34,2,c1,2,fe

SQL> COL SYS_NC_01 FORMAT A30
SQL> SELECT SYS_NC_01, DUMP(SYS_NC_01, 16) D_ROWID
  2  FROM SYS_IOT_MAP_32399;

SYS_NC_01                      D_ROWID
------------------------------ --------------------------------------------------
*BAAAAAACwQL+                  Typ=208 Len=10: 2,4,0,0,0,0,2,c1,2,fe

原来索引组织表的ROWID包括物理猜信息,而映射表保存的ROWID,没有记录物理地址信息,而只包括了索引组织表的主键。

那么索引组织表就有一个有趣的特性,可以通过多个ROWID访问相同的一条记录:

SQL> SELECT * FROM T_INDEX_ORG
  2  WHERE ROWID = '*BAJAADQCwQL+';

        ID NAME                           TYPE
---------- ------------------------------ ------------------------------
         1 T_INDEX_ORG                    IOT

SQL> SELECT * FROM T_INDEX_ORG
  2  WHERE ROWID = '*BAAAAAACwQL+';

        ID NAME                           TYPE
---------- ------------------------------ ------------------------------
         1 T_INDEX_ORG                    IOT

SQL> SELECT * FROM T_INDEX_ORG
  2  WHERE ROWID = '*BABCDAACwQL+';

        ID NAME                           TYPE
---------- ------------------------------ ------------------------------
         1 T_INDEX_ORG                    IOT

SQL> SELECT * FROM T_INDEX_ORG
  2  WHERE ROWID = '*BADDDDACwQL+';

        ID NAME                           TYPE
---------- ------------------------------ ------------------------------
         1 T_INDEX_ORG                    IOT

换句话说,只要ROWID包含的主键信息是正确的,就可以访问到对应的记录,而与逻辑ROWID中的物理地址是否存在、是否准确无关。

可以看到,前面两个ROWID分别是索引组织表真实的ROWID,以及映射表中保存的ROWID,但是后面两个ROWID,完全是根据ROWID的规则仿写的,而且居然也可以得到记录。

扯远一点,这一点就是逻辑ROWID和物理ROWID的一个重要区别。一条记录只有一个物理ROWID,而一个物理ROWID是在数据库中唯一的,它表示唯一一个物理地址,它可能对应到一条记录,也可能不对应任何一条记录。

而根据上面的结果也可以看到,多个逻辑ROWID可以指向同一条记录,也就是说1条记录对应多个逻辑ROWID。

而一个逻辑ROWID也可以指向多条记录,看一个简单的例子:

SQL> CREATE TABLE T_INDEX_ORG1
  2  (ID NUMBER PRIMARY KEY)
  3  ORGANIZATION INDEX;

表已创建。

SQL> INSERT INTO T_INDEX_ORG1 VALUES (1);

已创建 1 行。

SQL> SELECT ROWID FROM T_INDEX_ORG1;

ROWID
-----------------------------------------
*BAJABSwCwQL+

SQL> ALTER TABLE T_INDEX_ORG1 MOVE MAPPING TABLE;

表已更改。

SQL> SELECT TABLE_NAME, IOT_NAME, IOT_TYPE
  2  FROM USER_TABLES
  3  WHERE IOT_TYPE IS NOT NULL;

TABLE_NAME                     IOT_NAME                       IOT_TYPE
------------------------------ ------------------------------ ------------
SYS_IOT_MAP_32399              T_INDEX_ORG                    IOT_MAPPING
SYS_IOT_MAP_32427              T_INDEX_ORG1                   IOT_MAPPING
T_INDEX_ORG                                                   IOT
T_INDEX_ORG1                                                  IOT

SQL> SELECT * FROM SYS_IOT_MAP_32427;

SYS_NC_01
------------------------------
*BAAAAAACwQL+

SQL> SELECT * FROM T_INDEX_ORG
  2  WHERE ROWID = '*BAAAAAACwQL+';

        ID NAME                           TYPE
---------- ------------------------------ ------------------------------
         1 T_INDEX_ORG                    IOT

SQL> SELECT * FROM T_INDEX_ORG1
  2  WHERE ROWID = '*BAAAAAACwQL+';

        ID
----------
         1

同一个逻辑ROWID可以指向不同表中的不同记录,只要它们的主键信息是相同的。

于是可以看到一个十分有趣的SQL:

SQL> SELECT A.ROWID, B.ROWID
  2  FROM T_INDEX_ORG A, T_INDEX_ORG1 B
  3  WHERE A.ROWID = B.ROWID;

ROWID                                     ROWID
----------------------------------------- ------------------------------------
*BAJAADQCwQL+                             *BAJABUwCwQL+

两个ROWID明明不等,但是居然可以查询出结果。这就是逻辑ROWID特点所造成的。

这次扯的真是有点远了,还是回到最初的话题。

可以看到,对于建立了映射表的索引组织表,在做任何修改的时候,都会同步修改映射表中的ROWID信息。而如果是通过ALTER TABLE MOVE MAPPING TABLE添加的映射表,会自动将目前索引组织表中所有记录的ROWID,添加到映射表中。

SQL> SELECT * FROM T_INDEX_ORG;

        ID NAME                           TYPE
---------- ------------------------------ --------------------
         1 T_INDEX_ORG                    IOT

SQL> SELECT * FROM SYS_IOT_MAP_32399;

SYS_NC_01
------------------------------
*BAAAAAACwQL+

SQL> UPDATE T_INDEX_ORG SET ID = 2;

已更新 1 行。

SQL> SELECT * FROM SYS_IOT_MAP_32399;

SYS_NC_01
------------------------------
*BAJAADQCwQP+

当记录的主键发生变化的时候,Oracle也会更新映射表中保存的逻辑ROWID信息。

在Oracle确保映射表和索引组织表的同步的情况下,就可以利用映射表来创建BITMAP索引了。

Oracle之所以无法直接在索引组织表上建立BITMAP索引,是因为BITMAP索引保存的是一个个ROWID范围,在这些范围内通过BITMAP来对应表的ROWID信息。而索引组织表的实际存储格式是索引,而索引的根节点、分支节点和叶节点都保存在一起,因此实际保存表数据的叶节点在一个EXTENT中是不连续的。

建立了映射表后,BITMAP索引实际是建立在映射表这个堆表上,通过映射表中保存的逻辑ROWID信息,对应到索引组织表中。

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4227/viewspace-670807/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1964
  • 访问量
    11077234