[20150720]为什么8K数据块Hakan Factor=736

[20150720]为什么8K数据块Hakan Factor=736.txt

--前几天被别人问及这个问题,还真不好回答。
--仔细思考,我觉得与行迁移有关,行迁移发生时,rowid不会变化。数据信息被移动另外的块,在块内保留一个指针。
--也就是讲最小这条记录仅仅包含一个rowid指针。
--还是通过例子来说明情况:

1.建立测试环境:
SCOTT@test> @&r/ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- ----------------------------------------------------------------
x86_64/Linux 2.4.xx            10.2.0.4.0     Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi

SCOTT@test> create table test (id varchar2(100)) pctfree 0 tablespace mssm ;
Table created.

SCOTT@test> insert into test select null from dba_objects where rownum<=1000;
1000 rows created.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> select rowid,test.* from test where rownum<=1;
ROWID              ID
------------------ -------
AAAQZYAAGAAAAAKAAA

SCOTT@test> @&r/lookup_rowid AAAQZYAAGAAAAAKAAA
      OBJECT         FILE        BLOCK          ROW DBA                  TEXT
------------ ------------ ------------ ------------ -------------------- ----------------------------------------
       67160            6           10            0 6,10                 alter system dump datafile 6 block 10 ;

SCOTT@test> select count(*)  from test where rowid between 'AAAQZYAAGAAAAAKAAA' and 'AAAQZYAAGAAAAAKDDD';
    COUNT(*)
------------
         734

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

-- 1块 仅仅734 条记录,比规定最大少3条记录。(注意spare1=736,也就是最大行号736,实际上就是每块最大插入737条记录(行号从0开始).)

SCOTT@test> alter system checkpoint;
System altered.

2.通过bbed观察:
BBED> set dba 6,10
        DBA             0x0180000a (25165834 6,10)

BBED> p *kdbr[0]
rowdata[1437]
-------------
ub1 rowdata[1437]                           @7423     0x2c

BBED> x /rcccc
rowdata[1437]                               @7423
-------------
flag@7423: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@7424: 0x01
cols@7425:    0

BBED> x /rc
rowdata[1437]                               @7423
-------------
flag@7423: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@7424: 0x01
cols@7425:    0

--可以发现NULL并没有记录,一条记录仅仅占用3个字节。 2c 01 00

BBED> map
File: /mnt/ramdisk/test/mssm01.dbf (6)
Block: 10                                    Dba:0x0180000a
------------------------------------------------------------
KTB Data Block (Table/Cluster)
struct kcbh, 20 bytes                      @0
struct ktbbh, 72 bytes                     @20
struct kdbh, 14 bytes                      @92
struct kdbt[1], 4 bytes                    @106
sb2 kdbr[734]                              @110
ub1 freespace[4408]                        @1578
ub1 rowdata[2202]                          @5986
ub4 tailchk                                @8188

-- freespace = 4408 , 几乎一半的空间剩下。2202/3=734,说明信息对上。

BBED> p kdbr[733]
sb2 kdbr[733]                               @1576     6563

--说明块头部包括行目录,已经占用1578字节。

--这样留给数据部分是:

8192-1578-4=6610 (扣除尾部tailchk4个字节)
6610/734=9.0054495912806539595
6610-734*9=4

--这样计算也就是每条记录最多9个字节。每条记录前面已经占用3个字节,这样仅仅剩下6个字节。(仅仅够保留rowid)
--做一个大胆的猜测,如果734条记录全部发生行迁移,rowid指针必须保留,这样正好够。

--换一句话讲假设修改如下:
update test set id='1' where rowid='AAAQZYAAGAAAAAKAAA';

--仅仅1条记录,在这样的情况下(注意记录前面有1个字节保存字符串长度)就不会发生行迁移,但是如果修改如下:
update test set id='123456' where rowid='AAAQZYAAGAAAAAKAAA';

--这样有会发生行迁移,继续测试看看:

3.继续测试:
SCOTT@test> update test set id='1' where rowid='AAAQZYAAGAAAAAKAAA';
1 row updated.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> alter system checkpoint;
System altered.

BBED> set dba 6,10
        DBA             0x0180000a (25165834 6,10)

BBED> p *kdbr[0]
rowdata[0]
----------
ub1 rowdata[0]                              @5981     0x2c

BBED> x /rc
rowdata[0]                                  @5981
----------
flag@5981: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@5982: 0x02
cols@5983:    1

col    0[1] @5984: 1

--没有发生行迁移。
SCOTT@test> update test set id='12' where rowid='AAAQZYAAGAAAAAKAAA';
1 row updated.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> alter system checkpoint;
System altered.

BBED> x /rc
rowdata[0]                                  @5975
----------
flag@5975: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@5976: 0x01
cols@5977:    1

col    0[2] @5978: 12

--没有发生行迁移。
SCOTT@test> update test set id='123' where rowid='AAAQZYAAGAAAAAKAAA';
1 row updated.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> alter system checkpoint;
System altered.

BBED> x /rc
rowdata[0]                                  @5968
----------
flag@5968: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@5969: 0x02
cols@5970:    1

col    0[3] @5971: 123

SCOTT@test> update test set id='1234' where rowid='AAAQZYAAGAAAAAKAAA';
1 row updated.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> alter system checkpoint;
System altered.

BBED> x /rc
rowdata[0]                                  @5960
----------
flag@5960: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@5961: 0x01
cols@5962:    1
col    0[4] @5963: 1234

--继续:
SCOTT@test> update test set id='12345' where rowid='AAAQZYAAGAAAAAKAAA';
1 row updated.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> alter system checkpoint;
System altered.

BBED> x /rc
rowdata[0]                                  @5951
----------
flag@5951: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@5952: 0x02
cols@5953:    1

col    0[5] @5954: 12345

SCOTT@test> update test set id='1234567' where rowid='AAAQZYAAGAAAAAKAAA';
1 row updated.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> alter system checkpoint;
System altered.

--恩,奇怪并没有出现我想象的情况。

BBED> x /rc
rowdata[0]                                  @5930
----------
flag@5930: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@5931: 0x02
cols@5932:    1

col    0[7] @5933: 1234567

4.重来看看:

SCOTT@test> drop table test purge ;
Table dropped.

SCOTT@test> create table test (id varchar2(100)) pctfree 0 tablespace mssm ;
Table created.

SCOTT@test> insert into test select null from dba_objects where rownum<=1000;
1000 rows created.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> select rowid,test.* from test where rownum<=1;
ROWID              ID
------------------ ----------------------------------------------------------------------------------------------------
AAAQZdAAGAAAAAKAAA

SCOTT@test> @ &r/lookup_rowid AAAQZdAAGAAAAAKAAA
      OBJECT         FILE        BLOCK          ROW DBA                  TEXT
------------ ------------ ------------ ------------ -------------------- ----------------------------------------
       67165            6           10            0 6,10                 alter system dump datafile 6 block 10 ;

SCOTT@test> update test set id='12345' where rowid='AAAQZdAAGAAAAAKAAA';
1 row updated.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> alter system checkpoint;
System altered.

BBED> set dba 6,10
        DBA             0x0180000a (25165834 6,10)

BBED> p *kdbr[0]
rowdata[0]
----------
ub1 rowdata[0]                              @5977     0x20

BBED> x /rc
rowdata[0]                                  @5977
----------
flag@5977: 0x20 (KDRHFH)
lock@5978: 0x02
cols@5979:    0
nrid@5980:0x0180000b.10a

--奇怪慢慢增加不行,也许更oracle内部算法有关。bvi观察到 20 02 00 01 80 00 0B 01 0A(9个字节),注意这里rowid全面没有长度指示器。

5.全部update看看:
SCOTT@test> update test set id='12345' ;
1000 rows updated.

SCOTT@test> commit ;
Commit complete.

SCOTT@test> alter system checkpoint;
System altered.

BBED> map
File: /mnt/ramdisk/test/mssm01.dbf (6)
Block: 10                                    Dba:0x0180000a
------------------------------------------------------------
KTB Data Block (Table/Cluster)
struct kcbh, 20 bytes                      @0
struct ktbbh, 72 bytes                     @20
struct kdbh, 14 bytes                      @92
struct kdbt[1], 4 bytes                    @106
sb2 kdbr[734]                              @110
ub1 freespace[4]                           @1578
ub1 rowdata[6606]                          @1582
ub4 tailchk                                @8188

--这样仅仅剩下4自己。几乎没有剩下的空间。可以发现每条记录都发生了行迁移。

BBED> p *kdbr[1]
rowdata[6588]
-------------
ub1 rowdata[6588]                           @8170     0x20

BBED> x /rc
rowdata[6588]                               @8170
-------------
flag@8170: 0x20 (KDRHFH)
lock@8171: 0x01
cols@8172:    0
nrid@8173:0x0180000b.10b

--从以上分析可以推出计算最大行号(Hakan Factor)按照剩余空间/每条记录9字节来计算的。
--因为每个行目录占2个字节。加上每条记录9个字节。
(8192-110-4)=8078/11=734.36

--为什么少了几条呢,我推测:
--9i下建表仅仅1个itl槽,而现在这样有2个itl槽,注ctas建表有3个itl槽。这样多出了24字节。
--这样算下来正好多处2条记录。加起来正好是736,不过还是差1(行号从0开始).

8192-110-4+24=8102
8102/11=736.54

--我测试表空间是SEGMENT SPACE MANAGEMENT MANUAL。如果是SEGMENT SPACE MANAGEMENT AUTO,还要少1条,是733.
--大家可以在自行测试。有机会测试9i就清楚了。

时间: 2024-07-30 10:46:53

[20150720]为什么8K数据块Hakan Factor=736的相关文章

[20121019]8k数据块到底能放多少行记录.txt

[20121019]8k数据块到底能放多少行记录.txt 前一阵子聚会,被问及一个8k数据块能够放多少行记录,我记得以前piner的书提高过,73X条. 实际上表sys.tab$的spare1字段保存的Hakan Factor,即该表数据块的最大行号,各种数据块的大小不同, spare1的缺省值也不一样. _______________________________ 块大小  最大行数每块(spare1)   _______________________________ 2K      17

[20140813关于Hakan factor.txt

[20140813关于Hakan factor.txt --曾经写过一篇通过执行ALTER TABLE MINIMIZE RECORDS_PER_BLOCK避免行迁移的blog. http://blog.itpub.net/267265/viewspace-763315/ --里面的Hakan factor主要用来唯一映射表上行在位图索引.可以表示表的单个数据块的最大行数. --记录在sys.tab$的spare1里面. --昨天我查看随机安装的example例子发现一个奇怪的情况.自己也做一些

[20161123]oracle数据块类型.txt

[20161123]oracle数据块类型.txt --oracle 数据块有许多类型,自己平时很少关注与记忆,自己做一个归纳总结: 1.环境: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        BANNER ------------------------------ -------------- ------------------------------------------------------

修复损坏的数据块

  bbed就是英文block browse block edit的缩写,用来直接查看和修改数据文件数据的一个工具 在windows上提供工具dbv,在linux上面有,需要编译:make -f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed 然后把$ORACLE_HOME/rdbms/lib加到环境变量的PATH里面,就可以直接在命令中bbed了.编译好了就可以使用了,不过有个默认的口令blockedit.运行bbed之前先要自己写几个配置文件:这里有2个 a

【体系结构】Oracle数据块详解

Oracle数据块详解 操作系统块是操作系统读写的最小操作单元,也是操作系统文件的属性之一.当创建一个Oracle数据库时,选择一个基于操作系统块的整数倍大小作为Oracle数据库块的大小.Oracle数据库读写操作则是以Oracle块为最小单位,而非操作系统块. 数据库块也称逻辑块或Oracle块,它对应磁盘上一个或多个物理块,它的大小由初始化参数DB_BLOCK_SIZE决定,可以定义数据块为2K.4K.8K.16K.32K甚至更大,默认Oracle块大小是8K.若一旦设置了Oracle数据

数据块转储及RDBA的转换

数据|转换 数据块转储及RDBA的转换 原文链接: http://www.eygle.com/internal/How_to_dump_datablock.htm Tuesday, 2004-08-31 17:51 Eygle  很多时候我们在进行进一步研究时需要转储(dump)Oracle的数据块,以研究其内容,Oracle提供了很好的方式,我们通过以下例子简单说明一下: [oracle@jumper udump]$ sqlplus "/ as sysdba"SQL*Plus: Re

网页制作教程:框架、布局、模块、列表和数据块

做前端也有几年时间了,不敢说能把他看地多透,但是多多少少还是有些自己的东西.就制作而言,我将一张页面分为四层:框架.布局.模块.列表和数据块. 一.框架 页面的框架基本上都是:"头"."主体"."尾".但是对于一 些页面如Tudou.com,由于布局的需要,还应在"头"的下面还要加个"菜单". 二.布局(以下用#ID表示页面元素) #Head和#Foot里的就不说了,具体查看演示页面源码. 布局说的是将#M

明明白白使用数据块:数据块格式深入解析

Data Block是数据库中最小的I/O单元,下面我来简单介绍下数据块的基本结构. OK!跟着我一步步实验: 一.建表空间 SQL>create tablespace tp1 datafile '/oradata/bxocp/tp01.dbf' size 10M; 二.建用户及授权 SQL>create user gyj identified by gyj default tablespace tp1; SQL>grant dba to gyj; 三.建表 SQL>conn gy

如何使用DUMP数据块与BBED查看BLOCK对比数据库修改时的SCN

实验思路: 先在数据库中对bys.a表的一行进行更新,查出此行对应的FILE# BLOCK# 然后DUMP此FILE# BLOCK#,查看SCN信息 使用BBED DUMP此FILE# BLOCK#,查看SCN信息 1.在数据库中对 bys.a表的一行进行更新,记录此行的ROWID. 19:55:13 BYS@ bys3>select * from a; B ---------- 55 7 3 19:55:15 BYS@ bys3>update a  set b=0 where b=7; 1