[20150204]关于位图索引5.txt

简介: [20150204]关于位图索引5.txt --许多人知道在oltp系统不适合使用位图索引.它的索引的记录结构如下是: 字段0:键值 字段1:开始rowid 字段2:结束rowid 字段3:位图信息,指示那行记录,位图1=>表示存在.

[20150204]关于位图索引5.txt

--许多人知道在oltp系统不适合使用位图索引.它的索引的记录结构如下是:
字段0:键值
字段1:开始rowid
字段2:结束rowid
字段3:位图信息,指示那行记录,位图1=>表示存在.位图0=>表示不存在.

--但是字段4的位图信息,介绍的资料太少,我自己看了链接http://juliandyke.com/Presentations/BitmapIndexInternals.ppt,做一个简单探究.

--前面的讲解仅仅在1个数据块的情况,如果开始rowid与结束rowid在不同数据块的情况呢?自己再做一些验证.
--在验证前我讲一下Hakan Factor:

. Hakan Factor can be adjusted using
  ALTER TABLE table_name MINIMIZE RECORDS_PER_BLOCK;
. This command
  . Scans entire table
  . Counts number of rows in each block
  . Sets Hakan Factor in SPARE1  to maximum row count
  . Sets bit 0x8000 in SPARE1  to indicate value has been set
. Subsequently modified blocks will be limited to the new Hakan Factor
. Command is reversed using
ALTER TABLE table_name NOMINIMIZE RECORDS_PER_BLOCK;

--Hakan Factor 概括讲就是设置1个块能插入的最大行号(也限制了插入行记录的数量).信息保存在sys.tab$的spare1字段中,等于
--0x8000+记录最大行号.使用它最大好处:

Hakan Factor
. Hakan Factor is used when compressing bitmaps
. Each bitmap represents an array Blocks
Maximum rows per block
. Minimising records per block reduces size of this array Blocks Maximum rows per block
. Reduces memory required to access/manipulate bitmap
. May reduce disk space required to hold bitmap

--实际上使用它可以位图信息大小,减少磁盘空间占用.实际上我以前自己测试过,减少的量可以讲很少,因为位图编码可以压缩许多信息.
--总之使用它效果不是很明显,但是那它来控制1块插入的记录数,控制发生行迁移的情况倒是一个不错的选择.
--先测试使用Hakan Factor的情况:

1.建立测试环境:
SCOTT@test> @ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.3.0     Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

--drop table t purge;
create table t(id number , name varchar2(10), status varchar2(1));
insert into t select rownum-1 id,dbms_random.string('X',10) c20,decode(mod((rownum-1),8),0,'Y','N') c1 from dual connect by levelcommit ;

alter table t minimize records_per_block;
insert into t select 66+rownum-1 id,dbms_random.string('X',10) c20,decode(mod((rownum-1),8),1,'Y','N') c1 from dual connect by levelcommit;

create bitmap index ib_t_status on t(status);

SCOTT@test> select rowid,t.* from t where id=0 or id=66;
ROWID                      ID NAME                 S
------------------ ---------- -------------------- -
AABI+7AAEAAAACjAAA         66 5AUDMDRUO4           N
AABI+7AAEAAAACnAAA          0 DXMRIJ3Y7X           Y

SCOTT@test> @lookup_rowid AABI+7AAEAAAACjAAA
    OBJECT       FILE      BLOCK        ROW DBA                  TEXT
---------- ---------- ---------- ---------- -------------------- ----------------------------------------
    298939          4        163          0 4,163                alter system dump datafile 4 block 163 ;

SCOTT@test> @lookup_rowid AABI+7AAEAAAACnAAA
    OBJECT       FILE      BLOCK        ROW DBA                  TEXT
---------- ---------- ---------- ---------- -------------------- ----------------------------------------
    298939          4        167          0 4,167                alter system dump datafile 4 block 167 ;

SCOTT@test> select owner,segment_name,header_file,header_block  from dba_segments where owner=user and segment_name='IB_T_STATUS';
OWNER  SEGMENT_NAME         HEADER_FILE HEADER_BLOCK
------ -------------------- ----------- ------------
SCOTT  IB_T_STATUS                    4          530


SCOTT@test> select spare1 from sys.tab$ where obj#=298939;
    SPARE1
----------
     32833

SCOTT@test> select 32833-32768 from dual;
32833-32768
-----------
         65
--可以发现复合前面的设置.
--以上是我加入Hakan Factor的情况,现在我取消Hakan Factor设置,并且重新建立索引看看.

SCOTT@test> alter table t nominimize records_per_block;
alter table t nominimize records_per_block
*
ERROR at line 1:
ORA-28602: statement not permitted on tables containing bitmap indexes
--可以发现包含位图索引不能取消Hakan Factor.

SCOTT@test> drop index ib_t_status ;
Index dropped.

SCOTT@test> alter table t nominimize records_per_block;
Table altered.

SCOTT@test> create bitmap index ib_t_status on t(status);
Index created.

--删除位图索引后,可以正常操作.
SCOTT@test> select spare1 from sys.tab$ where obj#=298939;
    SPARE1
----------
       736

-- spare1等于736 .

SCOTT@test> alter system checkpoint ;
System altered.

SCOTT@test> alter system dump datafile 4 block 531 ;
System altered.

row#0[7991] flag: ------, lock: 0, len=41
col 0; len 1; (1):  4e
col 1; len 6; (6):  01 00 00 a3 00 00
col 2; len 6; (6):  01 00 00 a7 00 47
col 3; len 22; (22):
cf fd fd fd fd fd fd fd fd 00 ff e5 02 fe fe fe fe fe fe fe fe 01
row#1[7950] flag: ------, lock: 0, len=41
col 0; len 1; (1):  59
col 1; len 6; (6):  01 00 00 a3 00 00
col 2; len 6; (6):  01 00 00 a7 00 47
col 3; len 22; (22):
cf 02 02 02 02 02 02 02 02 01 ff e5 02 01 01 01 01 01 01 01 01 00
----- end of leaf block dump -----

--还是拿status='Y'的col3来说明:
--01 00 00 a3, 对应是dba是4,163.
--01 00 00 a7, 对应是dba是4,167.
SCOTT@test> @dfb 010000a7
    RFILE#     BLOCK#
---------- ----------
         4        167

--  cf 02 02 02 02 02 02 02 02 01 ff e5 02 01 01 01 01 01 01 01 01 00
-- cf 拆开:
-- 11 001 111
-- 11 大于192.表示Multi-Byte Groups
-- 001 表示 0个字节0
-- 111 表示8个字节长度.
-- 这个块4,163,id>=66,我设置是第2位是status='Y',这样后面的02就对上了.

-- 注意后面还有1个01,这个前面讲的单字节组,表示01000000,也就是这个8位的第2位,id就是 66+64+2-1=131.
SCOTT@test> select * from t where status='Y' and id>=66;
        ID NAME                 S
---------- -------------------- -
        67 P3C2R82UGA           Y
        75 L2D0D32P6X           Y
        83 NRTTL3ZR0P           Y
        91 TS7A2RIY5Y           Y
        99 Q1PDWVU8CH           Y
       107 JN9YJXAGWE           Y
       115 VS4972RXU0           Y
       123 S7URPXY9AY           Y
       131 DEK3H4PG6G           Y
9 rows selected.

--说明正好对上.

--继续拆分
-- ff e5 02 01 01 01 01 01 01 01 01 00
-- ff e5 02 拆开:

-- 11 111 111 , 1110 0101, 0000 0010
-- 11 大于192.表示Multi-Byte Groups
-- 111,必须考虑下面的扩展 0xe5(229),注意这里高位是1.第3个字节是02,表示扩展了2次.(我乱猜的)
-- 这样6+2*128+229-128 =363,表示 363个字节0
-- 下面的111 表示8个字节长度.

--这样拆分下俩就是:
363*8 个0 , 00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001

-- 注意后面还有1个00,这个前面讲的单字节组,表示10000000,也就是这个8位的第1位,id就是 64+1-1=64.
-- 实际上这个问题363*8(也就是363*8=2904)个0 如何得来的?

SCOTT@test> select header_file,header_block from dba_segments where owner=user and segment_name='T';
HEADER_FILE HEADER_BLOCK
----------- ------------
          4          162

4.163 使用 id = 66,131
4,164
4,165
4,166
4.167 使用 id = 1,65

--从rowid开始与结束看,跳过了3个块file#=4,164,165,166块.
--现在spare1=736,也就是最大行号736,实际上就是每块最大插入737条记录(行号从0开始).因为位图信息是8位为一组.这样向8位取整,
--[注:真不知道为什么要浪费1个字节]
-- 737/8=92.125, 93*3=279
-- 不对啊....................陷入困境... 噢忽略了4,163块仅仅占用72位,9个字节.
-- 这样还有  93-9=84 字节没有使用.
-- 279+84=363 ,这样就对上了,也不知道自己的分析是否正确.


===转抄前面的资料:
1.首先前面2位一定是11,只有这样才能大于192.也叫控制位.
2.下面3位表示0字节的数量.
         字节数量      0bit的数量 
=================================
001         0               0
010         1               8
011         2              16 
100         3              24
101         4              32
110         5              40
==================================

其中3位=111,必须扩展到下一字节.

                          字节数量      0bit的数量 
==================================================
111000 00000000                  6            48
111000 00000001                  7            56
111000 00000010                  8            64
....
111000 01111111                133      133*8=1064
111000 10000000 00000001       134      134*8=1072
111000 10000001 00000001       135      135*8=1080
==================================================

. Last three bits indicate number of bytes following control block (minimum 1, maximum 8)
--最后3位是表示位图信息的长度,这里注意000,表示后面占用1个字节. ... 111表示占用8个字节.
===

目录
相关文章
|
SQL 测试技术 索引
[20180509]函数索引问题.txt
[20180509]函数索引问题.txt https://jonathanlewis.wordpress.com/2018/05/07/fbis-dont-exist/ --//重复测试: 1.
1095 0
|
关系型数据库 Linux 索引
[20180212]函数索引问题.txt
[20180212]函数索引问题.txt --//11g下,如果函数索引,字段出现重复,出现ORA-54015: Duplicate column expression was specified.
981 0
|
SQL Oracle 关系型数据库
[20171206]位图区一定在数据文件开头吗.txt
[20171206]位图区一定在数据文件开头吗.txt --//如果问你oracle数据文件的位图区位于数据文件开头部分吗?我想大家的回答一定,实际上在10g下未必,因为10g建立的数据文件.
1046 0
|
存储 索引
|
物联网 索引
[20151008]索引组织表上创建BITMAP索引.txt
[20151008]索引组织表上创建BITMAP索引.txt --IOT 是一种特殊的索引结构,使用它能够解决特定场合的应用问题,但是在许多应用中很少使用,更多的是使用堆表。
924 0
|
测试技术 索引
[20150926]索引压缩问题.txt
[20150926]索引压缩问题.txt --以前如果索引前缀重复值很多,我会选择索引压缩,这样减少磁盘空间占用,索引范围扫描也可以减少磁盘IO,虽然这样可能消耗一些 --CUP资源,感觉影响不大。
872 0
|
SQL Oracle 关系型数据库
[20150803]使用函数索引注意的问题.txt
[20150803]使用函数索引注意的问题.txt --昨天在10g下优化时遇到一个奇怪的问题,做一个记录: --首先说明一下,最近一段时间在做一个项目的优化,这个项目实际上ETL项目: http://baike.
842 0
|
索引
[20150321]索引空块的问题.txt
[20150321]索引空块的问题.txt --晚上看了: 索引空块较多造成index range scan的IO成本较高 http://www.dbaxiaoyu.
735 0
|
SQL 关系型数据库 索引
[20150205]关于位图索引6.txt
[20150205]关于位图索引6.txt --许多人知道在oltp系统不适合使用位图索引.它的索引的记录结构如下是: 字段0:键值 字段1:开始rowid 字段2:结束rowid 字段3:位图信息,指示那行记录,位图1=>表示存在.
830 0
|
测试技术 数据库管理 索引
[20150205]关于位图索引7.txt
[20150205]关于位图索引7.txt --许多人知道在oltp系统不适合使用位图索引.它的索引的记录结构如下是: 字段0:键值 字段1:开始rowid 字段2:结束rowid 字段3:位图信息,指示那行记录,位图1=>表示存在.
987 0