最近正在看老白的《DBA的思想天空》,了解数据块结构,想通过dump data block验证oracle对于行尾的NULL,是不占用存储空间的。
我们先来看一下怎样dump数据块:
1.在数据库级别dump数据库,oracle提供了命令支持
ALTER SYSETM DUMP DATAFILE absolute_file_number
BLOCK block_number;
ALTER SYSETM DUMP DATAFILE absolute_file_number
BLOCK MIN minimum_block_number
BLOCK MAX maximum_block_number;
ALTER SYSETM DUMP DATAFILE 'file_name'
BLOCK block_number;
如果需要强制dump出来的数据以十六进制显示,需要设置event 10289
ALTER SESSION SET EVENTS
'10289 trace name context forever, level 1';
然后再dump数据块,使用下列命令关闭10289
ALTER SESSION SET EVENTS
'10289 trace name context off';
需要注意的是:
- dump是,如果忽略block参数,将dump整个数据文件
- 使用文件号(absolute_file_number)是,数据库必须处于OPEN状态,并且数据文件也要求ONLINE;
- 使用文件号,dump信息来自Buffer Cache,而不是磁盘
- 使用文件名,dump信息来自磁盘,因此实例在NOMOUNT状态也可以dump
2.通过操作系统工具dump
dd if=/s01/app/oracle/oradata/MYAPP/users01.dbf of=b527.dmp bs= skip= count=
OK,补充了dump的知识,让我们来跟随老白的实验,验证null是不占用存储空间的。
CREATE TABLE TEST1 (A INTEGER,B VARCHAR2(100),C VARCHAR2(100);
INSERT INTO TEST1 VALUES (1,null,'aaaa');
INSERT INTO TEST1 VALUES (2,null,'bbbb');
INSERT INTO TEST1 VALUES (1,'',null);
然后查找这个extent所在的位置:
SELECT extent_id,file_id,block_id from dba_extents where segment_name='TEST1' and owner='SCOTT';
EXTENT_ID FILE_ID BLOCK_ID
---------- ---------- ----------
0 4 520
然后我们查询TEST1表的ROWID
SQL> select dbms_rowid.rowid_block_number('AAASwvAAEAAAAIPAAA') block# from dual;
BLOCK#
---------------------------------------------------
527
通过dd命令可以看到这三条数据。
选中部分2C 01 02:02代表长度。这里也可以验证数据块里的数据是从下往上分布的。
或者alter system dump datafile:
block_row_dump:
tab 0, row 0, @0x1f8c
tl: 12 fb: --H-FL-- lb: 0x1 cc: 3
col 0: [] c1 02
col 1: *NULL*
col 2: [] 61 61 61 61
tab 0, row 1, @0x1f80
tl: 12 fb: --H-FL-- lb: 0x1 cc: 3
col 0: [] c1 03
col 1: *NULL*
col 2: [] 62 62 62 62
tab 0, row 2, @0x1f74
tl: 12 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 02
col 1: [ 5] 31 31 31 31 31
end_of_block_dump
End dump data blocks tsn: 4 file#: 4 minblk 527 maxblk 527
可以看到 INSERT INTO TEST1 VALUES (1,'11111',null); dump出来只有两列数据,NULL是不占用空间的。