前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >新增字段在数据块中的体现

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

作者头像
bisal
发布2021-09-06 15:57:10
9960
发布2021-09-06 15:57:10
举报
文章被收录于专栏:bisal的个人杂货铺

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

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

代码语言:javascript
复制
SQL> create table testadd(id number, name varchar2(1));
Table created.

...

SQL> select * from testadd;
 ID N
---------- -
  1 a
  2 b

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

代码语言:javascript
复制
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

场景一

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

代码语言:javascript
复制
SQL> alter table testadd add a1 varchar2(1);
Table altered.

此时的数据块,无任何的变化,标记表的字段,仍然是两个,

代码语言:javascript
复制
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

如果更新已存在的一条数据的这个新增字段,

代码语言:javascript
复制
SQL> update testadd set a1='a' where id=1;
1 row updated.

SQL> commit;
Commit complete.

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

代码语言:javascript
复制
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

如果新增记录,

代码语言:javascript
复制
SQL> insert into testadd values(3, 'c', 'c');
1 row created.

SQL> commit;
Commit complete.

我们看到数据块中的第三条新增记录,已经包含了三个字段,

代码语言:javascript
复制
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

说明当增加一个不带默认值,不带非空约束的字段时,只有当该字段存储值,数据块中才会为其实际存储。

场景二

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

代码语言:javascript
复制
SQL> alter table testadd add a2 varchar2(1) default 'a';
Table altered.

此时我们看到,数据块中都实际存储了这个新增字段,至于原因,同学们应该了解,新增带着默认值,不带非空约束的字段,其实会执行一个全表更新的操作,会实际为该新增字段插入数据, 具体可参考《新增字段的一点一滴技巧》,

代码语言:javascript
复制
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. 应该是存储顺序上的需求,第二个字段原先未实际存储的第三个列此时做了占位。

场景三

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

代码语言:javascript
复制
SQL> alter table testadd add a3 varchar2(1) default 'a' not null;
Table altered.

新增的a3字段已经有了值,

代码语言:javascript
复制
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

但是此时数据块,并未实际存储这个新增字段,

代码语言:javascript
复制
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

如果此时新增一条记录,

代码语言:javascript
复制
SQL> insert into testadd values(4, 'd', 'a', 'a', 'a'); 
1 row created.

SQL> commit;
Commit complete.

此时数据块中,第四条记录,已经包含了五个字段,其他记录,仍是四个字段,

代码语言:javascript
复制
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

如果更新一条已存在的记录,

代码语言:javascript
复制
SQL> update testadd set a3='a' where id=1;
1 row updated.

SQL> commit;
Commit complete.

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

代码语言:javascript
复制
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

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

  1. 新增字段带默认值的情况下,是否设置了非空约束。
  2. 该字段是否包含了值(包含让default设置的)。
  3. 该字段即使为空,但是在他之后,新增了其他包含值的字段,则该字段会在数据块中显示为*NULL*的占位。

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/07/15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档