oracle 中关于 超过253列 内部数据的存储
2012-10-20 12:33
267 查看
建表语句 declare v_sql varchar2(32767) ; begin v_sql := 'create table test ( ' ; for i in 1..500 loop v_sql := v_sql || 'name'||i||' varchar2(2000) ,' ; end loop ; v_sql := substr(v_sql,1,length(v_sql)-1) ; v_sql := v_sql || ');' ; dbms_output.put_line(v_sql) ; end ; 复制粘贴创建表 _dex@D***ID> desc test Name Null? Type ----------------------------------------------------- -------- ------------------------------------ NAME1 VARCHAR2(2000) NAME2 VARCHAR2(2000) NAME3 VARCHAR2(2000) ..... NAME500 VARCHAR2(2000) _dex@D***ID> insert into test (name500) values (lpad(1,300,'d')) ; 1 row created. _dex@D***ID> select 2 length(t.name500), 3 dbms_rowid.rowid_relative_fno(t.rowid) as "FNO#", 4 dbms_rowid.rowid_block_number(t.rowid) as "BLK#", 5 dbms_rowid.rowid_row_number(t.rowid) as "ROW#" 6 from dex.test t 7 / LENGTH(T.NAME500) FNO# BLK# ROW# ----------------- ---------- ---------- ---------- 300 4 925 1 1 4 925 3 300 4 925 5 使用bbed查看 首先看row#为1长度为300的数据 BBED> set dba 4,925 DBA 0x0100039d (16778141 4,925) BBED> p kdbr sb2 kdbr[0] @142 7504 sb2 kdbr[1] @144 7250 sb2 kdbr[2] @146 6991 sb2 kdbr[3] @148 6737 sb2 kdbr[4] @150 6177 sb2 kdbr[5] @152 5923 BBED> p *kdbr[1] rowdata[1327] ------------- ub1 rowdata[1327] @7374 0x28 BBED> dump /v offset 7374 count 128 File: /u01/apps/oracle/oradata/david/users01.dbf (4) Block: 925 Offsets: 7374 to 7501 Dba:0x0100039d ------------------------------------------------------- 2801f501 00039d00 00ffffff ffffffff l (.õ............. ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ <16 bytes per line> 这些是row piece header 2801f501 00039d00 00 1个字节的flag=28 16进制28=二进制00101000=--H-F---=head of rowpiece + first data piece 1个字节的lb(itl slot)=01 1个字节的cc column count=f5=245 (因为最后一列name500不为空,所以null都需要使用ff来表示,也就是说需要存储500列的数据) 4个字节的dba 01 00039d=使用dbms_utility.DATA_BLOCK_ADDRESS_FILE以及dbms_utility.DATA_BLOCK_ADDRESS_BLOCK可以以此查询到文件以及block编号 具体: select dbms_utility.DATA_BLOCK_ADDRESS_FILE(to_number('0100039d','xxxxxxxxxx')) file#, dbms_utility.DATA_BLOCK_ADDRESS_BLOCK(to_number('0100039d','xxxxxxxxxx')) block# from dual; _sys@D***ID> / FILE# BLOCK# ---------- ---------- 4 925 也就是datafile 4 block 925 就在本块内 2个字节的row# 00 00 表示kdbr[0] 剩下的就是表示null的ff了 BBED> p *kdbr[1] rowdata[1327] ------------- ub1 rowdata[1327] @7374 0x28 BBED> p *kdbr[0] rowdata[1581] ------------- ub1 rowdata[1581] @7628 0x04 7628-7374=254字节(从offset7374开始到7628结束,不包括7628) 其中 9个字节的row header 所以存放row data 的空间为254-9=245字节 因为有245列的null值并且最后一列不为空,所以null都使用ff表示(一个字节),一共消耗了245字节。 我们再来看它的last data piece BBED> p *kdbr[0] rowdata[1581] ------------- ub1 rowdata[1581] @7628 0x04 BBED> dump /v offset 7628 count 1000 File: /u01/apps/oracle/oradata/david/users01.dbf (4) Block: 925 Offsets: 7628 to 8191 Dba:0x0100039d ------------------------------------------------------- 0401ffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ ffffffff ffffffff ffffffff ffffffff l ................ fffe2c01 64646464 64646464 64646464 l .t,.dddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646464 l dddddddddddddddd 64646464 64646464 64646464 64646431 l ddddddddddddddd1 01060aa4 l ...¤ 这些是row piece header 0401ff 其中 1个字节的flag=04 16进制4=二进制00000100=-----L--=last data piece 1个字节的lb(itl slot)=01 1个字节的cc column count=ff=255 (因为最后一列name500不为空,所以null都需要使用ff来表示) 总结,当超过了列的数量253,就会将row分裂为多个data piece 存放(类似row chain),每次还是使用1个字节的column count 来表示列的数量。 另外,最后一列的数据类型为varchar2(2000) 这里使用的是3个字节在存储它的长度 fe2c01 怎样计算呢? 使用后两个字节来表示 具体: 最后的1个字节表示256的个数比如这里为01 表示 256*1=256 再加上前一个字节的个数2c=44 256+44=300 估计fe是一个计算的标示符,因为没有找到相关资料,只能使用实验来证实了。 类似的, 253=fefd00 255=feff00 256=fe0001 257=fe0101 258=fe0201 259=fe0301 510=fefe01 512=fe0002 513=fe0102 2000=fed007 经过不断的实验测试得出 当length大于250的时候 就会使用3个字节类似于 fe fb00 来表示长度 length为250以及以下的长度 会以一个字节来表示长度 fe为长度位,后两位为长度值。因为是little endian 所以后两个字节需要颠倒过来 510=fefe01 512=fe0002 513=fe0102 其实是16进制 510=01fe 512=0200 513=0201 感谢擎天包的解答。
相关文章推荐
- 计算机内部如何存储数据,关于源码、补码的问题!
- Android App将数据写入内部存储和外部存储的示例
- 关于ORACLE时间存储的问题
- Oracle基本数据类型存储格式浅析(一)——字符类型
- 关于Oracle中,char、nchar、varchar、nvarchar存储汉字是所需要的字节数
- Java调用oracle存储过程通过游标返回临时表数据
- 【ORACLE】删除表数据的存储过程backup.sql
- Android中关于内部存储的一些重要函数
- 数据存储—读写内部存储的文件数据
- [oracle] Oracle存储过程里操作BLOB的字节数据的办法,例如写入32位整数
- 从零开始学android<数据存储(2)Internal Storage内部存储.三十六.>
- 关于UEditor插件的使用以及UEditor数据回显问题,数据库存储标签代码前台页面如何解析问题小结
- 关于在存储过程中动态选择数据表名
- Oracle与DB2数据存储模式的区别详解
- Android数据存储之Internal Storage内部存储
- ORACLE 数据存储结构之逻辑存储结构
- Oracle 导出、导入某用户所有数据(包括表、视图、存储过程...)
- 关于Vmware EXSI的数据存储
- 计算机内部浮点型数据的存储