ITPub博客

首页 > 数据库 > 国内数据库 > 【新炬网络名师大讲堂】Oracle中大表添加带有默认值列的讨论(包括11G,12C新特性)

【新炬网络名师大讲堂】Oracle中大表添加带有默认值列的讨论(包括11G,12C新特性)

国内数据库 作者:shsnchyw 时间:2015-02-04 14:59:01 0 删除 编辑

(本文转自“NCN新炬网络团队博客”)

这个问题为什么要讨论呢,是有历史根源的

我们从10G开始说起

在11G以前,一个大表,如果要添加一个新列,且新列有默认值,如果使用alter table xx add xx_1 number default 1000; 这类语句设置,那造成的后果是非常恐怖的。

它的动作其实就是,添加一个列,然后对这一列进行更新,如果这个表非常大,那么将会产生一个非常大的事务。

而且因为它是ddl操作,它甚至会导致关于该表的select语句都被堵塞!后果非常可怕。

我们在10G中,遇到这种需求怎么办呢?

简单来说,就是先添加一列(不设置默认值)

之后通过使用PL/SQL 对这一列进行批量提交更新(比如1000行 一提交)

好处是,不会锁太多的行,而且每个事务都不大,出现故障之类的,不会产生死事务

这里分享一个批量提交更新的脚本模版

declare
row_num number :=0;
begin
for c_test in (select rowid from hankdai) loop
update hankdai t set NewColumn=1000 where t.rowid=hank_test.rowid;
row_num := row_num + 1;
if mod(row_num,2000) = 0 then
commit;
end if;
end loop;
commit;
end;

当然,这里还可以使用在线重定义的方式。

http://blog.csdn.net/dbcrocodile/article/details/21512945 ,参考我的这篇博客

到了11G中,我们对于表添加一列 带有默认值,有了新特性

我们来测试一下,创建表t,100多万数据。

SQL> select count(*) from t;

COUNT(*)
———-
1207317

对表加了一列,并设置not null 加默认值

SQL> alter table t add MrDai number default 10000 not null;

Table altered.

Elapsed: 00:00:00.34

速度飞快

这里其实只是在数据字典中做了一个标记,并不会对块中行的实际数据进行修改,所以速度飞快

我们查询的时候,会对新列做一个类似nvl()之类的操作,如果是null,则返回默认的数值。

在设置完成以后,如果是新插入的行,在默认值列,会将数据真正的插入到行

总结一下,这个特性类似于 给表设了一个断点, 断点之前的,如果该列是null,则对其转换为 默认值,而断点之后的,该列会插入真正的值

这里存在一个问题,就是我上面标红的not null。

毕竟一个新特性在口口相传中可能会漏掉一些东西,比如最重要的not null 如果漏了

那么将会产生与10G中相同的灾难,超大DDL事务,hang死关于该表的一切操作(包括select)

这种误操作可以说是非常容易发生的,看看下面这两个语句有多像。

alter table t add MrDai1 number default 10000;
alter table t add MrDai1 number default 10000 not null;

OK。既然提出了可能会存在这种误操作事故可能性,那么我就一定要提出一个解决方案,否则这博客岂不是玩笑了

12C。对这个功能再次做出了增强,这个增强最重要的就是将这个误操作消除了。也就是说,大表添加默认值新列时,不用加not null 也可以实现metadata only 的增加方式。

实现如下:

百万表

SQL> select count(*) from t;

COUNT(*)
———-
1454256

对表直接增加一列(不设置not null)

SQL> alter table t add MrDai number default 10000;

Table altered.

Elapsed: 00:00:00.03

—————————————————————————————————————————–

 

上面主题讨论完了,看起来不起眼的更新,其实在我们实际运用过程中影响却十分巨大,所以有什么新特性,一定要首先实验实验再实验,将语句写好,到业务库上建议复制粘贴。减少各种非常不 必要的误操作。

—————————————————————————————————————————-

上面讨论了12C中default列增强的一种,那么将12C中关于default列的增强的其他部分也讨论一下。

12C中default列方面增强了三块。

1、default列metadata only增强(既我们上面讨论过的特性)

2、default值直接使用sequence

3、显式插入null值,依然将其变成default值特性(on null子句)

第一个特性我们已经讨论过了,开始从第二个特性讨论。

default值直接使用sequence

12C之前情况

创建sequence

SQL> create sequence t_seq;

Sequence created.

SQL>create table t1 (
id number default  t_seq.nextval,

*
name varchar2(20)
4 );

ERROR at line 2:
ORA-00984: column not allowed here

说明,在12C之前,如果想产生一个顺序默认值作为列值,必须在insert里面做文章,如下

SQL>create table t1 (id number,
name varchar2(20)
);

Table created.

SQL> insert into t1 values(t_seq.nextval,’haha’);

1 row created.

Elapsed: 00:00:00.00

SQL> insert into t1 values(t_seq.nextval,’haha’);

1 row created.

Elapsed: 00:00:00.00

SQL> select * from t1;

ID NAME
———- ——————–
1 haha
2 haha

这里是11G的情况,到了12C我们可以在表创建的过程中直接指定某列默认值为sequence值的nextval,currval

SQL> create sequence t_seq;

Sequence created.

Elapsed: 00:00:00.03
create table t1 (
id number default t_seq.nextval,
name varchar2(20)
4 );

Table created.

Elapsed: 00:00:00.08

插入数据(仅插入name列,id列不输入值)

SQL> insert into t1(name) values(‘haha’);

1 row created.

Elapsed: 00:00:00.00

SQL> insert into t1(name) values(‘haha’);

1 row created.

Elapsed: 00:00:00.00

SQL> select * from t1;

ID NAME
———- ——————–
1 haha
2 haha

我们再也不用羡慕sqlserver中列值自增长了。

————————————————————————————-

显式插入null值,依然将其变成default值特性(on null子句)

该特性不好描述,直接看实验算了。

创建两个sequence

SQL> create sequence t_seq;

Sequence created.
SQL> create sequence t2_seq;

Sequence created.

创建表t1,id,name ,id2 三列,并在id2列使用on null 子句
SQL>create table t1 (
id number default t_seq.nextval,
name varchar2(20),
id2 number default on null t2_seq.nextval
5 );

Table created.

插入数据

第一行,显式指定三列值

SQL> insert into t1(id,name,id2) values(1,’Hank’,101);

1 row created.

第二行,显式指定name列值

SQL> insert into t1(name) values(‘Hank2′);

1 row created.

第三行,显式指定id,id2为null,name列值为hank3

SQL> insert into t1(id,name,id2) values(null,’Hank3′,null);

1 row created.

查看三行分别的结果。

SQL> select * from t1;

ID NAME ID2
———- ——————– ———-
1 Hank 101                                                  —- 三列都为原本指定的值
1 Hank2 1                                                    —–1列和3列分别都为默认的sequence值
Hank3 2                                                   —–显 式指定null后,id2 on null列 也插入默认值2,而id列则插入显式指定的null值。

这就是区别,描述的不好,但实验结果应该是蛮清楚的。

原文链接:http://ncn.cn/archivers/oracle%e4%b8%ad%e5%a4%a7%e8%a1%a8%e6%b7%bb%e5%8a%a0%e5%b8%a6%e6%9c%89%e9%bb%98%e8%ae %a4%e5%80%bc%e5%88%97%e7%9a%84%e8%ae%a8%e8%ae%ba%ef%bc%88%e5%8c%85%e6%8b%ac11g12c%e6%96%b0%e7%89%b9%e6%80%a7.html

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29960155/viewspace-1426263/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2014-10-16

  • 博文量
    147
  • 访问量
    268239