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

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博客 ” ,链接:http://blog.itpub.net/4227/viewspace-670807/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/4227/viewspace-670807/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值