生产过程中常常会遇到对表需要在线增加列,尤其是新增带缺省值的非空列,例如:

ALTER TABLE .. ADD COLUMN ( ... NOT NULL DEFAULT ... )

在Oracle 11g以前,执行这条DDL会涉及以下步骤:

在数据字典中中增加新列定义:列类型、长度、NOT NULL及DEFAULT等;

更新表上所有行,使用新列的缺省值增加新列的值。

对百万级以上的大表,该DDL可能会耗费较长时间及系统资源,同时也会对该表进行长时间加锁,影响业务的正常使用。

Oracle 11g起引入了新的隐藏参数:_ADD_COL_OPTIM_ENABLED。如果数据库参数:COMPATIBLE>=11时,则_ADD_COL_OPTIM_ENABLED缺省为TRUE。

_ADD_COL_OPTIM_ENABLED值为True时,新增带缺省值非空列的DDL会仅仅将新列添加到表定义中,但是不会更新实际的表行记录。 内部会在数据字典中存储一个标志,对于没有列值的行均会返回DEFAULT值。 对于大表,这会节省大量资源和加快执行速度。 在数据库内部,访问该表的任何代码路径都会查询数据字典设置,为该列返回正确的数据。该 参数的设置仅影响新的“ ADD COLUMN”命令。 一旦使用此种方式增加新的列,则数据字典中的标志将指示该特定列已被优化。可以通过以下查询获取已优化的列:

col object_name format a30

set lines 100

select owner, object_name, name

from dba_objects, col$

where bitand(col$.PROPERTY,1073741824)=1073741824

and object_id=obj#;

下面通过几个简单案例来分析下列值在数据块中的存储变化。

准备

测试数据库:11.2.0.4

compatible=11.2.0.4

_add_col_optim_enabled=true

SQL> create table test.t_obj(c1 varchar2(1));

Table created.

SQL> insert into test.t_obj values('1');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from test.t_obj;

C

-

1

SQL> select dbms_rowid.rowid_object(rowid) obj#,

dbms_rowid.rowid_relative_fno(rowid) rfile#,

dbms_rowid.rowid_block_number(rowid) block#,

dbms_rowid.rowid_row_number(rowid) row#

from test.t_obj; 2 3 4 5

OBJ# RFILE# BLOCK# ROW#

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

70623 4 134 0

SQL> alter system checkpoint;

System altered.

SQL> alter system dump datafile 4 block 134;

System altered.

查看trace文件:

Block header dump: 0x01000086

Object id on Block? Y

seg/obj: 0x113df csc: 0x00.95330 itc: 2 flg: E typ: 1 - DATA

brn: 0 bdba: 0x1000080 ver: 0x01 opc: 0

inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x000a.011.000010a8 0x00c028a4.00cb.26 --U- 1 fsc 0x0000.00095331

0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

bdba: 0x01000086

data_block_dump,data header at 0x7f96a71b3264

===============

tsiz: 0x1f98

hsiz: 0x14

pbl: 0x7f96a71b3264

76543210

flag=--------

ntab=1

nrow=1

frre=-1

fsbo=0x14

fseo=0x1f93

avsp=0x1f7b

tosp=0x1f7b

0xe:pti[0] nrow=1 offs=0

0x12:pri[0] offs=0x1f93

block_row_dump:

tab 0, row 0, @0x1f93

tl: 5 fb: --H-FL-- lb: 0x1 cc: 1

col 0: [ 1] 31

end_of_block_dump

End dump data blocks tsn: 4 file#: 4 minblk 134 maxblk 134

案例一:新增带缺省值的非空列

SQL> alter table test.t_obj add c2 varchar2(1) default 'a' not null;

Table altered.

SQL> col binarydefval format a10

select ec.* from sys.ecol$ ec,sys.obj$ o where ec.tabobj#=o.dataobj#;

SQL>

TABOBJ# COLNUM BINARYDEFV

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

70623 2 61

SQL> select c1,c2,dbms_rowid.rowid_object(rowid) obj#,

dbms_rowid.rowid_relative_fno(rowid) rfile#,

dbms_rowid.rowid_block_number(rowid) block#,

dbms_rowid.rowid_row_number(rowid) row#

from test.t_obj; 2 3 4 5

C C OBJ# RFILE# BLOCK# ROW#

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

1 a 70623 4 134 0

SQL> col object_name format a30

set lines 100

select owner, object_name, name

from dba_objects, col$

where bitand(col$.PROPERTY,1073741824)=1073741824

and object_id=obj#;

OWNER OBJECT_NAME NAME

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

TEST T_OBJ C2

SQL> alter system checkpoint;

System altered.

SQL> alter system dump datafile 4 block 134;

System altered.

查看trace文件:

Block header dump: 0x01000086

Object id on Block? Y

seg/obj: 0x113df csc: 0x00.95330 itc: 2 flg: E typ: 1 - DATA

brn: 0 bdba: 0x1000080 ver: 0x01 opc: 0

inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x000a.011.000010a8 0x00c028a4.00cb.26 --U- 1 fsc 0x0000.00095331

0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

bdba: 0x01000086

data_block_dump,data header at 0x7f96a71b3264

===============

tsiz: 0x1f98

hsiz: 0x14

pbl: 0x7f96a71b3264

76543210

flag=--------

ntab=1

nrow=1

frre=-1

fsbo=0x14

fseo=0x1f93

avsp=0x1f7b

tosp=0x1f7b

0xe:pti[0] nrow=1 offs=0

0x12:pri[0] offs=0x1f93

block_row_dump:

tab 0, row 0, @0x1f93

tl: 5 fb: --H-FL-- lb: 0x1 cc: 1

col 0: [ 1] 31

end_of_block_dump

查询返回了期望的列值,但在数据块实际没有存储(根据Oracle内部机制,因为是NULL,所以未在数据块中存储)。

案例二:修改非空列的default

在案例一的基础上继续

SQL> alter table test modify (c2 default 'b');

Table altered.

SQL> select ec.* from sys.ecol$ ec,sys.obj$ o where ec.tabobj#=o.dataobj#;

TABOBJ# COLNUM BINARYDEFV

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

70623 2 61

SQL> select column_name,data_default from dba_tab_columns where owner='TEST';

COLUMN_NAME DATA_DEFAULT

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

C1

C2 'b'

SQL> insert into test.t_obj(c1) values('2');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from test.t_obj;

C C

- -

1 a

2 b

SQL> select c1,c2,dbms_rowid.rowid_object(rowid) obj#,

dbms_rowid.rowid_relative_fno(rowid) rfile#,

dbms_rowid.rowid_block_number(rowid) block#,

dbms_rowid.rowid_row_number(rowid) row#

from test.t_obj; 2 3 4 5

C C OBJ# RFILE# BLOCK# ROW#

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

1 a 70623 4 134 0

2 b 70623 4 134 1

SQL> alter system checkpoint;

System altered.

SQL> alter system dump datafile 4 block 134;

System altered.

Block header dump: 0x01000086

Object id on Block? Y

seg/obj: 0x113df csc: 0x00.95330 itc: 2 flg: E typ: 1 - DATA

brn: 0 bdba: 0x1000080 ver: 0x01 opc: 0

inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x000a.011.000010a8 0x00c028a4.00cb.26 --U- 1 fsc 0x0000.00095331

0x02 0x000a.01b.0000109b 0x00c028aa.00cb.03 --U- 1 fsc 0x0000.0009558d

bdba: 0x01000086

data_block_dump,data header at 0x7f96a71b3264

===============

tsiz: 0x1f98

hsiz: 0x16

pbl: 0x7f96a71b3264

76543210

flag=--------

ntab=1

nrow=2

frre=-1

fsbo=0x16

fseo=0x1f8c

avsp=0x1f70

tosp=0x1f70

0xe:pti[0] nrow=2 offs=0

0x12:pri[0] offs=0x1f93

0x14:pri[1] offs=0x1f8c

block_row_dump:

tab 0, row 0, @0x1f93

tl: 5 fb: --H-FL-- lb: 0x1 cc: 1

col 0: [ 1] 31

tab 0, row 1, @0x1f8c

tl: 7 fb: --H-FL-- lb: 0x2 cc: 2

col 0: [ 1] 32

col 1: [ 1] 62

end_of_block_dump

新插入的行,非空列使用了修改后的default值,已有行继续使用原有的default值。

案例三:将非空列去除非空属性

在案例二的基础上继续

SQL> alter table test.t_obj modify c2 null;

Table altered.

SQL> select ec.* from sys.ecol$ ec,sys.obj$ o where ec.tabobj#=o.dataobj#;

no rows selected

SQL> select column_name,data_default from dba_tab_columns where owner='TEST';

COLUMN_NAME DATA_DEFAULT

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

C1

C2 'b'

SQL> select c1,c2,dbms_rowid.rowid_object(rowid) obj#,

dbms_rowid.rowid_relative_fno(rowid) rfile#,

dbms_rowid.rowid_block_number(rowid) block#,

dbms_rowid.rowid_row_number(rowid) row#

from test.t_obj; 2 3 4 5

C C OBJ# RFILE# BLOCK# ROW#

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

1 a 70623 4 134 0

2 b 70623 4 134 1

SQL> alter system checkpoint;

System altered.

SQL> alter system dump datafile 4 block 134;

System altered.

Block header dump: 0x01000086

Object id on Block? Y

seg/obj: 0x113df csc: 0x00.95643 itc: 2 flg: E typ: 1 - DATA

brn: 0 bdba: 0x1000080 ver: 0x01 opc: 0

inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x000a.004.000010a3 0x00c028ab.00cb.04 --U- 2 fsc 0x0000.0009564a

0x02 0x000a.01b.0000109b 0x00c028aa.00cb.03 C--- 0 scn 0x0000.0009558d

bdba: 0x01000086

data_block_dump,data header at 0x7f96a71b3264

===============

tsiz: 0x1f98

hsiz: 0x16

pbl: 0x7f96a71b3264

76543210

flag=--------

ntab=1

nrow=2

frre=-1

fsbo=0x16

fseo=0x1f85

avsp=0x1f70

tosp=0x1f70

0xe:pti[0] nrow=2 offs=0

0x12:pri[0] offs=0x1f85

0x14:pri[1] offs=0x1f8c

block_row_dump:

tab 0, row 0, @0x1f85

tl: 7 fb: --H-FL-- lb: 0x1 cc: 2

col 0: [ 1] 31

col 1: [ 1] 61

tab 0, row 1, @0x1f8c

tl: 7 fb: --H-FL-- lb: 0x1 cc: 2

col 0: [ 1] 32

col 1: [ 1] 62

end_of_block_dump

此时可以看到数据块中的列值发生了变化,原有的NULL更新为具体值。对于大表来说,这个操作将较为耗时。

案例四:继续增加带缺省值的非空列和不带缺省值的空列

在案例三的基础上继续

SQL> alter table test.t_obj add c3 varchar2(1) default 'c' not null;

Table altered.

SQL> select c1,c2,c3,dbms_rowid.rowid_object(rowid) obj#,

dbms_rowid.rowid_relative_fno(rowid) rfile#,

dbms_rowid.rowid_block_number(rowid) block#,

dbms_rowid.rowid_row_number(rowid) row#

from test.t_obj; 2 3 4 5

C C C OBJ# RFILE# BLOCK# ROW#

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

1 a c 70623 4 134 0

2 b c 70623 4 134 1

SQL> select ec.* from sys.ecol$ ec,sys.obj$ o where ec.tabobj#=o.dataobj#;

TABOBJ# COLNUM BINARYDEFV

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

70623 3 63

SQL> alter system checkpoint;

System altered.

SQL> alter table test.t_obj add c4 varchar2(1);

Table altered.

SQL> insert into test.t_obj(c1,c4) values('3','3');

1 row created.

SQL> commit;

Commit complete.

SQL> select c1,c2,c3,c4,dbms_rowid.rowid_object(rowid) obj#,

dbms_rowid.rowid_relative_fno(rowid) rfile#,

dbms_rowid.rowid_block_number(rowid) block#,

dbms_rowid.rowid_row_number(rowid) row#

from test.t_obj; 2 3 4 5

C C C C OBJ# RFILE# BLOCK# ROW#

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

1 a c 70623 4 134 0

2 b c 70623 4 134 1

3 b c 3 70623 4 134 2

Block header dump: 0x01000086

Object id on Block? Y

seg/obj: 0x113df csc: 0x00.95643 itc: 2 flg: E typ: 1 - DATA

brn: 0 bdba: 0x1000080 ver: 0x01 opc: 0

inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x000a.004.000010a3 0x00c028ab.00cb.04 --U- 2 fsc 0x0000.0009564a

0x02 0x000a.01a.000010a8 0x00c028ac.00cb.1a --U- 1 fsc 0x0000.000957eb

bdba: 0x01000086

data_block_dump,data header at 0x7f96a71b3264

===============

tsiz: 0x1f98

hsiz: 0x18

pbl: 0x7f96a71b3264

76543210

flag=--------

ntab=1

nrow=3

frre=-1

fsbo=0x18

fseo=0x1f7a

avsp=0x1f63

tosp=0x1f63

0xe:pti[0] nrow=3 offs=0

0x12:pri[0] offs=0x1f85

0x14:pri[1] offs=0x1f8c

0x16:pri[2] offs=0x1f7a

block_row_dump:

tab 0, row 0, @0x1f85

tl: 7 fb: --H-FL-- lb: 0x1 cc: 2

col 0: [ 1] 31

col 1: [ 1] 61

tab 0, row 1, @0x1f8c

tl: 7 fb: --H-FL-- lb: 0x1 cc: 2

col 0: [ 1] 32

col 1: [ 1] 62

tab 0, row 2, @0x1f7a

tl: 11 fb: --H-FL-- lb: 0x2 cc: 4

col 0: [ 1] 33

col 1: [ 1] 62

col 2: [ 1] 63

col 3: [ 1] 33

end_of_block_dump

案例五:alter table move的影响

在案例四基础上继续:

SQL> alter table test.t_obj move;

Table altered.

SQL> alter system checkpoint;

System altered.

SQL> select c1,c2,c3,c4,dbms_rowid.rowid_object(rowid) obj#,

dbms_rowid.rowid_relative_fno(rowid) rfile#,

dbms_rowid.rowid_block_number(rowid) block#,

dbms_rowid.rowid_row_number(rowid) row#

from test.t_obj; 2 3 4 5

C C C C OBJ# RFILE# BLOCK# ROW#

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

1 a c 70624 4 139 0

2 b c 70624 4 139 1

3 b c 3 70624 4 139 2

SQL> alter system dump datafile 4 block 139;

System altered.

Block header dump: 0x0100008b

Object id on Block? Y

seg/obj: 0x113e0 csc: 0x00.9594b itc: 3 flg: E typ: 1 - DATA

brn: 0 bdba: 0x1000088 ver: 0x01 opc: 0

inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x000a.020.000010ad 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

bdba: 0x0100008b

data_block_dump,data header at 0x7f96a71b327c

===============

tsiz: 0x1f80

hsiz: 0x18

pbl: 0x7f96a71b327c

76543210

flag=--------

ntab=1

nrow=3

frre=-1

fsbo=0x18

fseo=0x1f63

avsp=0x1f4b

tosp=0x1f4b

0xe:pti[0] nrow=3 offs=0

0x12:pri[0] offs=0x1f77

0x14:pri[1] offs=0x1f6e

0x16:pri[2] offs=0x1f63

block_row_dump:

tab 0, row 0, @0x1f77

tl: 9 fb: --H-FL-- lb: 0x0 cc: 3

col 0: [ 1] 31

col 1: [ 1] 61

col 2: [ 1] 63

tab 0, row 1, @0x1f6e

tl: 9 fb: --H-FL-- lb: 0x0 cc: 3

col 0: [ 1] 32

col 1: [ 1] 62

col 2: [ 1] 63

tab 0, row 2, @0x1f63

tl: 11 fb: --H-FL-- lb: 0x0 cc: 4

col 0: [ 1] 33

col 1: [ 1] 62

col 2: [ 1] 63

col 3: [ 1] 33

end_of_block_dump

End dump data blocks tsn: 4 file#: 4 minblk 139 maxblk 139

结论

_ADD_COL_OPTIM_ENABLED=true生效后,可以实现大表的快速新增带缺省值的非空列,对于生产环境较有意义。

使用该特性增加列,需注意后期一些操作的影响,例如:not null改为null、alter table move等。

该参数优化仅对新增带缺省值的非空列有效,对带缺省值的空列无效。

Oracle 12c又引入了_add_nullable_column_with_default_optim参数,可以对新增带缺省值的空列也有效。

oracle 大表新增列 慢_Oracle DDL性能改进-大表新增列行为分析相关推荐

  1. Oracle 共享锁和排它锁、 DML和DDL锁、 for update 锁表的问题

    共享锁和排它锁 oracle有两种模式的锁:排他锁(exclusive lock,即X锁)和共享锁(share lock,即S锁). 共享锁:如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享 ...

  2. oracle 动态sql列转行_Oracle 行转列 动态出转换的列

    10月的第二天,前天写了个Oracle中行转列的pivot的基本使用方法,然后,因为pivot的用法中,正常情况下,我们需要转出多少个列,都得在我们的sql中完完整整地写出,而不能直接在里面写个查询来 ...

  3. oracle 建表id自增长_oracle 左连接、右连接、全外连接、内连接、以及 (+) 号用法...

    Oracle中的连接可分为,内连接(INNER JOIN).外连接(OUTER JOIN).全连接(FULL JOIN),不光是 Oracle,其他很多的数据库也都有这3种连接查询方式. Oracle ...

  4. Oracle数据库表连接查询并分页SQL语句提示未明确定义列

    Oracle数据库表连接查询并分页SQL语句提示未明确定义列 两张表中的字段: t_product t_category product_id category_id product_name cat ...

  5. oracle修改表字段名备注_oracle 增加修改删除表字段,添加修改表、以及表中字段的备注...

    添加字段的语法:alter table tablename add (column datatype [default value][null/not null],-.); 修改字段的语法:alter ...

  6. oracle修改表字段名备注_Oracle修改表或者字段的注释

    转自:https://www.cnblogs.com/fx-blog/p/7132833.html 语句: comment on table 表名 is '表的注释信息'; comment on co ...

  7. oracle通过表空间文件进行数据库恢复,Oracle数据库表空间恢复方案_oracle

    一. 用户表空间 错误: 在启动数据库时出现ORA-01157,ORA-01110或操作系统级错误例如ORA-07360,在关闭数据库(使用shutdown normal或shutdown immed ...

  8. a表两个字段都与b表一个字段关联_Oracle系列第二章----表,精彩延续。。。

    第一节 表的概念 表设计的原则 2.1 表 数据库中以表为组织单位存储数据.表用来存储一些事物的信息,首先需要有一个表名,以及存储的信息. 2.2 设计原则 好的数据库表设计会影响数据库操作效率.特别 ...

  9. oracle 会话数上不去_Oracle初识

    1.基本概念 oracle数据库是一个物理概念,oracle实例是数据库在内存中的镜像,属于一种逻辑概念. oracle数据库与oracle实例至少是一对一的关系,也可能是一对多关系(oracle集群 ...

最新文章

  1. CSS的一个FAQ问题——浮动层覆盖问题!!!
  2. HTTP学习记录:二、请求方法
  3. asp.net三层结构
  4. linux java 安装 gi_gi的安装和使用
  5. php七牛分片上传_ThinkPHP实现JavaScript上传大视频到七牛云实例
  6. 【POJ - 2392】Space Elevator (dp,优秀的背包问题)
  7. 后端在插入数据发现重复如何正确的弹出警告_前百度面试官整理的——Java后端面试题(一)...
  8. django-删除学生数据
  9. 内存、时间复杂度、CPU/GPU以及运行时间
  10. 【转】C# 中@符号在字符串中的作用
  11. 解决禁用IE设置代理检测不通过连不上网
  12. python绘制科赫雪花and科赫雪花进阶版
  13. C# 打印PDF文件之使用不同打印机打印所有页面或部分页面
  14. 腾讯IM请求报错腾讯IM:70421参数类型有问题
  15. 复制-粘贴大法(Copy-Paste):简单而有效的数据增强
  16. mysql 表改名_MySQL库改名、表改名
  17. MyBatis学习(二)--利用MyBatis实现CRUD操作
  18. charles常用功能使用说明
  19. Word 自动更新编号(插入题注、交叉引用)
  20. ::before和::after是什么?

热门文章

  1. 图像处理课设(奇怪版)
  2. 理光Ricoh MP C5503 一体机驱动
  3. 几种音视频信号转换的比较,VGA转HDMI,HDMI/VGA转AV/S-Video,AV转...
  4. 怎么还原xp系统里的服务器,xp怎么还原电脑网络设置
  5. DSP6678 RapidIO基本原理之一
  6. MPG格式(歌曲) 和 MPEG格式的区分
  7. shell编程之正则表达式——理论基础
  8. java波斯王子时之沙_我的世界Java版21w07a版本更新内容详情
  9. QT实现窗口置顶、置顶状态切换、多窗口置顶优先关系
  10. seo模拟点击软件_哪些SEO排名工具是有效的呢?