设为首页 收藏本站
查看: 617|回复: 0

[经验分享] Oracle Database 中 关于 null值的存储

[复制链接]
YunVN网友  发表于 2016-8-14 07:35:27 |阅读模式
  这里主要验证了number 和 varchar2 两种数据类型null值的存储

  先来介绍一下row piece的结构
  
  
  
  引用官方文档的一张结构图
DSC0000.jpg

  

  通常情况下,不包括(cluster table 和 chain row)一个rowpiece 包括row header 和 column data
  关于其他情况,会在以后的研究中陆续放出。
  
  BBED> dump /v
File: /u01/apps/oracle/oradata/david/users01.dbf(4)
Block: 531 Offsets: 8173to 8191Dba:0x01000213
-------------------------------------------------------
3c020302 c1020353 59530444 55414c01 l<...á..SYS.DUAL.
06fbd4        l .ûÔ
<16 bytes per line>
  
例如:一个rowpiece的前3个字节 3c0203它表示
1个字节的flag

1个字节的lb(itl slot)

1个字节的columncount
  如例中

3c=flag=00111100=--HDFL--=header+delete+first+last

02=lb itl slot 0x02

03=column count



列值信息包括:

列的长度,列的value

例如02c102

表示占用2个byte

c102 表示的是具体的值
  dump 的信息 可以使用 UTL_RAW.CAST_TO_xxxx 来翻译(感谢itpubiori809的指导)
  

  

DSC0001.jpg
  

  下面开始验证
  首先环境为11.1.0.6 linux x64
  

dex@FAKE> desc ts
Name                                                              Null?    Type
----------------------------------------------------------------- -------- --------------------------------------------
ID                                                                         NUMBER
NAME                                                                       VARCHAR2(20)
COUNT                                                                      NUMBER

dex@FAKE> select t.*,
2         dbms_rowid.rowid_relative_fno(t.rowid) as "FNO#",
3         dbms_rowid.rowid_block_number(t.rowid) as "BLK#",
4         dbms_rowid.rowid_row_number(t.rowid) as "ROW#"
5    from dex.ts t
6  ;

ID NAME                      COUNT       FNO#       BLK#       ROW#
---------- -------------------- ---------- ---------- ---------- ----------
1 dd                                       4         31          0
2                               2          4         31          1
2                             3          4         31          2
4                                          4         31          3
  

建表语句:dex@FAKE> create table ts ( id number , name varchar2(20) , count number ) ;

因为表中没有使用long 类型的column,所以表中列的顺序和建表中的列的声明顺序相同。

BBED> set dba 4,31

DBA       0x0100001f (16777247 4,31)

BBED> map

File: /u01/apps/oracle/oradata/fake/users01.dbf (4)

Block: 31                  Dba:0x0100001f

------------------------------------------------------------

KTB Data Block (Table/Cluster)



struct kcbh, 20 bytes           @0   



struct ktbbh, 72 bytes           @20   



struct kdbh, 14 bytes           @100  



struct kdbt[1], 4 bytes          @114  



sb2 kdbr[3]                @118  



ub1 freespace[8036]            @124  



ub1 rowdata[28]              @8160  



ub4 tailchk                @8188  


首先看来看第一行id=1 的row#=0 的 rowpiece

BBED> p *kdbr[0]

rowdata[19]

-----------
  ub1 rowdata[19]

BBED> set offset 8179

OFFSET     8179

BBED> dump /v count 128

File: /u01/apps/oracle/oradata/fake/users01.dbf (4)

Block: 31   Offsets: 8179 to 8191 Dba:0x0100001f

-------------------------------------------------------

2c010202 c1020264 64010669 9f    l ,...Á..dd..i.



<16 bytes per line>

2c010202 c1020264 64 这些是rowpiece

第一行对应表中的值为

dex@FAKE> select * from ts where id=1 ;



ID NAME           COUNT

---------- -------------------- ----------

1 dd

可以看到id=1 的row#=0 ,这里的最后一列COUNT(number类型)值为null ,没有存储在block中,并且count number 标识为 拥有2列


我们再来看第二行 id=2 row#=1 的row piece


BBED> p *kdbr[1]

rowdata[9]

----------

ub1 rowdata[9]               @8169   0x2c

BBED> dump /v offset 8169 count 128

File: /u01/apps/oracle/oradata/fake/users01.dbf (4)

Block: 31   Offsets: 8169 to 8191 Dba:0x0100001f

-------------------------------------------------------

2c010302 c103ff02 c1032c01 0202c102 l ,...Á...Á.,...Á.

02646401 06699f           l .dd..i.



<16 bytes per line>
2c010302 c103ff02 c103 这些为第二行的rowpiece



对应表中的值为

ID NAME           COUNT

---------- -------------------- ----------

2                2

第二列name(varchar2类型) 为null

这里是怎样存储的呢?因为不是row piece 中的最后一列,可以看到是使用了ff来表示长度为0


再来看第三行 id=null row#=2 的row piece

BBED> p *kdbr[2]

rowdata[0]

----------

ub1 rowdata[0]               @8160   0x2c


BBED> dump /v offset 8160 count 128

File: /u01/apps/oracle/oradata/fake/users01.dbf (4)

Block: 31   Offsets: 8160 to 8191 Dba:0x0100001f

-------------------------------------------------------

2c0103ff 013202c1 042c0103 02c103ff l ,....2.Á.,...Á..

02c1032c 010202c1 02026464 0106699f l .Á.,...Á..dd..i.



<16 bytes per line>


rowpiece为 2c0103ff 013202c1 04



对应表中的值

dex@FAKE> select * from ts where id is null ;



ID NAME           COUNT

---------- -------------------- ----------

2               3

可以看到第一列id(number类型) 为null

也是使用ff来表示的。


最后看一下第四行 id=4 row#=3 的row piece



BBED> dump /v offset 8154 count 128

File: /u01/apps/oracle/oradata/fake/users01.dbf (4)

Block: 31   Offsets: 8154 to 8191 Dba:0x0100001f

-------------------------------------------------------

2c020102 c1052c01 03ff0132 02c1042c l ,...Á.,....2.Á.,

010302c1 03ff02c1 032c0102 02c10202 l ...Á...Á.,...Á..

64640206 b2a1            l dd..²¡



<16 bytes per line>



rowpiece 为2c020102 c105

对应表中的值为

dex@FAKE> select * from ts where id=4 ;



ID NAME           COUNT

---------- -------------------- ----------

4


可以看到row piece 中表示row piece 中只包含1列

因为后两列 name 与 count 的值都为空,所以也没有使用ff来表示。












想想也是蛮有道理的,如果不使用ff来表示,没有办法保证列的顺序。
  而当后面的列的值都为null的时候,自然可以省下1个字节的ff。
  至此验证结束






验证结束

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-257585-1-1.html 上篇帖子: Oracle DBA手记4:数据安全警示录 下篇帖子: oracle 死锁和锁等待的区别(转载)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表