新增字段在数据块中的体现

前几天同事提了一个问题,比较有意思,如果一张表新增字段,在数据块上是怎么存储的?是直接“加”到数据块中,还是通过其他的形式,表示新的字段?让我们从Oracle数据块内容,看下他到底是怎么存储的。

创建测试表,插入两条数据,

SQL> create table testadd(id number, name varchar2(1));
Table created.

SQL> select * from testadd;
ID N


1 a
2 b
我们从数据块中能看到这两条记录,

block_row_dump:
tab 0, row 0, @0x1f98
tl: 8 fb: –H-FL– lb: 0x1 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 61
tab 0, row 1, @0x1f90
tl: 8 fb: –H-FL– lb: 0x1 cc: 2
col 0: [ 2] c1 03
col 1: [ 1] 62

场景一

增加一个字段,不带默认值,不带非空约束,

SQL> alter table testadd add a1 varchar2(1);
Table altered.
此时的数据块,无任何的变化,标记表的字段,仍然是两个,

block_row_dump:
tab 0, row 0, @0x1f98
tl: 8 fb: –H-FL– lb: 0x1 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 61
tab 0, row 1, @0x1f90
tl: 8 fb: –H-FL– lb: 0x1 cc: 2
col 0: [ 2] c1 03
col 1: [ 1] 62
如果更新已存在的一条数据的这个新增字段,

SQL> update testadd set a1=’a’ where id=1;
1 row updated.

SQL> commit;
Commit complete.
我们看到,第一条记录的cc已经改成了3,同时多了col 2这个新增字段的列,但是第二条记录,仍是两个字段,

tab 0, row 0, @0x1f86
tl: 10 fb: –H-FL– lb: 0x1 cc: 3
col 0: [ 2] c1 02
col 1: [ 1] 61
col 2: [ 1] 61
tab 0, row 1, @0x1f90
tl: 8 fb: –H-FL– lb: 0x0 cc: 2
col 0: [ 2] c1 03
col 1: [ 1] 62
如果新增记录,

SQL> insert into testadd values(3, ‘c’, ‘c’);
1 row created.

SQL> commit;
Commit complete.
我们看到数据块中的第三条新增记录,已经包含了三个字段,

tab 0, row 0, @0x1f86
tl: 10 fb: –H-FL– lb: 0x1 cc: 3
col 0: [ 2] c1 02
col 1: [ 1] 61
col 2: [ 1] 61
tab 0, row 1, @0x1f90
tl: 8 fb: –H-FL– lb: 0x0 cc: 2
col 0: [ 2] c1 03
col 1: [ 1] 62
tab 0, row 2, @0x1f7c
tl: 10 fb: –H-FL– lb: 0x2 cc: 3
col 0: [ 2] c1 04
col 1: [ 1] 63
col 2: [ 1] 63
说明当增加一个不带默认值,不带非空约束的字段时,只有当该字段存储值,数据块中才会为其实际存储。

场景二

增加一个字段,带默认值,不带非空约束,

SQL> alter table testadd add a2 varchar2(1) default ‘a’;
Table altered.
此时我们看到,数据块中都实际存储了这个新增字段,至于原因,同学们应该了解,新增带着默认值,不带非空约束的字段,其实会执行一个全表更新的操作,会实际为该新增字段插入数据, 具体可参考《新增字段的一点一滴技巧》,

tl: 12 fb: –H-FL– lb: 0x1 cc: 4
col 0: [ 2] c1 02
col 1: [ 1] 61
col 2: [ 1] 61
col 3: [ 1] 61
tab 0, row 1, @0x1f65
tl: 11 fb: –H-FL– lb: 0x1 cc: 4
col 0: [ 2] c1 03
col 1: [ 1] 62
col 2: NULL
col 3: [ 1] 61
tab 0, row 2, @0x1f59
tl: 12 fb: –H-FL– lb: 0x1 cc: 4
col 0: [ 2] c1 04
col 1: [ 1] 63
col 2: [ 1] 63
col 3: [ 1] 61
P.S. 应该是存储顺序上的需求,第二个字段原先未实际存储的第三个列此时做了占位。

场景三

增加一个字段,带默认值,带非空约束,

SQL> alter table testadd add a3 varchar2(1) default ‘a’ not null;
Table altered.
新增的a3字段已经有了值,

SQL> select id, name, a1, a2, a3 from testadd;
ID NAME A1 A2 A3


1 a a a a
2 b a a
3 c c a a
但是此时数据块,并未实际存储这个新增字段,

tab 0, row 0, @0x1f70
tl: 12 fb: –H-FL– lb: 0x1 cc: 4
col 0: [ 2] c1 02
col 1: [ 1] 61
col 2: [ 1] 61
col 3: [ 1] 61
tab 0, row 1, @0x1f65
tl: 11 fb: –H-FL– lb: 0x1 cc: 4
col 0: [ 2] c1 03
col 1: [ 1] 62
col 2: NULL
col 3: [ 1] 61
tab 0, row 2, @0x1f59
tl: 12 fb: –H-FL– lb: 0x1 cc: 4
col 0: [ 2] c1 04
col 1: [ 1] 63
col 2: [ 1] 63
col 3: [ 1] 61
如果此时新增一条记录,

SQL> insert into testadd values(4, ‘d’, ‘a’, ‘a’, ‘a’);
1 row created.

SQL> commit;
Commit complete.
此时数据块中,第四条记录,已经包含了五个字段,其他记录,仍是四个字段,

tab 0, row 0, @0x1f70
tl: 12 fb: –H-FL– lb: 0x1 cc: 4
col 0: [ 2] c1 02
col 1: [ 1] 61
col 2: [ 1] 61
col 3: [ 1] 61
tab 0, row 1, @0x1f65
tl: 11 fb: –H-FL– lb: 0x1 cc: 4
col 0: [ 2] c1 03
col 1: [ 1] 62
col 2: NULL
col 3: [ 1] 61
tab 0, row 2, @0x1f59
tl: 12 fb: –H-FL– lb: 0x1 cc: 4
col 0: [ 2] c1 04
col 1: [ 1] 63
col 2: [ 1] 63
col 3: [ 1] 61
tab 0, row 3, @0x1f4b
tl: 14 fb: –H-FL– lb: 0x2 cc: 5
col 0: [ 2] c1 05
col 1: [ 1] 64
col 2: [ 1] 61
col 3: [ 1] 61
col 4: [ 1] 61
如果更新一条已存在的记录,

SQL> update testadd set a3=’a’ where id=1;
1 row updated.

SQL> commit;
Commit complete.
可以看到,第一条记录已经包含了五个字段,其他未更新记录,仍是四个字段,说明当增加一个带默认值,带非空约束的字段时,只有当该字段存储值,数据块中才会为其实际存储,

tab 0, row 0, @0x1f3d
tl: 14 fb: –H-FL– lb: 0x1 cc: 5
col 0: [ 2] c1 02
col 1: [ 1] 61
col 2: [ 1] 61
col 3: [ 1] 61
col 4: [ 1] 61
tab 0, row 1, @0x1f65
tl: 11 fb: –H-FL– lb: 0x0 cc: 4
col 0: [ 2] c1 03
col 1: [ 1] 62
col 2: NULL
col 3: [ 1] 61
tab 0, row 2, @0x1f59
tl: 12 fb: –H-FL– lb: 0x0 cc: 4
col 0: [ 2] c1 04
col 1: [ 1] 63
col 2: [ 1] 63
col 3: [ 1] 61
tab 0, row 3, @0x1f4b
tl: 14 fb: –H-FL– lb: 0x0 cc: 5
col 0: [ 2] c1 05
col 1: [ 1] 64
col 2: [ 1] 61
col 3: [ 1] 61
col 4: [ 1] 61

根据以上三个场景的测试,新增字段是否存在于数据块中,取决于几个条件,

新增字段带默认值的情况下,是否设置了非空约束。

该字段是否包含了值(包含让default设置的)。
该字段即使为空,但是在他之后,新增了其他包含值的字段,则该字段会在数据块中显示为NULL的占位。

无论什么问题,实践是检验真理的唯一标准。

新增字段相关的文章,

《新增字段的一点一滴技巧》

《新增非空约束字段在不同版本中的演进》

《alter table新增字段操作究竟有何影响?(下篇)》

近期更新的文章:

《SQL Server的索引碎片》

《MySQL客户端预读数据的区别》

《MySQL分组需求探秘》

《最近碰到的几个问题》

《小白学习MySQL – 查询会锁表?》

文章分类和索引:

《公众号700篇文章分类和索引》

声明:文中观点不代表本站立场。本文传送门:http://eyangzhen.com/423030.html

(0)
联系我们
联系我们
分享本页
返回顶部