Oracle 12c 新特性 --- metadata仅为空列的默认列值

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leo__1990/article/details/90032418

概念

The default values of columns are maintained in the data dictionary for columns specified as NULL.
对于指定为NULL的列,数据字典中维护列的默认值。
Adding new columns with DEFAULT values no longer requires the default value to be stored in all existing records. This not only enables a schema modification in sub-seconds and independent of the existing data volume, it also does not consume any space.
添加带有默认值的新列不再需要将默认值存储在所有现有记录中。这不仅允许在sub-seconds修改模式,而且独立于现有的数据卷,它也不会消耗任何空间。

在Oracle 11g之前,向现有表添加一个新列需要修改该表中的所有行,以添加新列。
Oracle 11g引入了元数据唯一默认值的概念。将默认子句添加到现有表的非空列,只涉及元数据更改,而不是对表中的所有行进行更改。优化器重写新列的查询,以确保结果与默认定义一致。
Oracle 12c更进一步,允许元数据默认值的强制和可选列。因此,在现有表中添加带有默认子句的新列将被作为一个元数据来处理,而不管该列是否被定义为不为空。这代表了空间保存和性能改进。

实验

1 在11g之前,如果您在表中添加了一个新的列,那么Oracle必须锁定和物理更新表中的所有行。可能是一个痛苦的过程,11g有一点帮助,为非空columns指定元数据的默认值,因此,更改仅在数据字典中完成,而不是在表数据中。

[[email protected] ~]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.4.0 Production on Thu Aug 24 20:50:27 2017

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

SQL> conn /as sysdba
Connected.
SQL> create table default_values (
      id number primary key
    );  2    3  

Table created.

SQL> insert into default_values values (1);

1 row created.

SQL> alter table default_values add def_w_not_null varchar2(20) default 'THIS IS DEFAULT' not null;

Table altered.

SQL> select * from default_values;

	ID      DEF_W_NOT_NULL
---------- ----------------------------------------
	 1      THIS IS DEFAULT

SQL> select * from table(dbms_xplan.display_cursor(null,null,'projection'));

...
   1 - "DEFAULT_VALUES"."ID"[NUMBER,22],
       NVL("DEFAULT_VALUES"."DEF_W_NOT_NULL",'THIS IS DEFAULT')[20]
...

因此,内部Oracle只是用下面的表达式重写列:NVL("DEFAULT_VALUES"."DEF_W_NOT_NULL",'THIS IS DEFAULT')

2 现在,增加了仅为空列添加元数据的默认值的可能性。让我们看看会发生什么:
SQL> select * from default_values;

	ID     DEF_W_NULL		   
---------- -------------------- 
	1      THIS IS DEFAULT2	         
SQL> select * from table(dbms_xplan.display_cursor(null,null,'projection'));

....

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - "DEFAULT_VALUES"."ID"[NUMBER,22],
       DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00002$",0)),NULL,NVL("DEFAULT_VALUES"."D
       EF_W_NULL",'THIS IS DEFAULT2'),'0',NVL("DEFAULT_VALUES"."DEF_W_NULL",'THIS
       IS DEFAULT2'),'1',"DEFAULT_VALUES"."DEF_W_NULL")[20],
...

我们现在有了更复杂的表达: DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00002$",0)),NULL,NVL("DEFAULT_VALUES"."DEF_W_NULL",'THIS IS DEFAULT2'),'0',NVL("DEFAULT_VALUES"."DEF_W_NULL",'THIS IS DEFAULT2'),'1',"DEFAULT_VALUES"."DEF_W_NULL"),还有一个新的隐藏列SYS_NC00002$

因此…只有行存在以前没有默认值写入数据块,所有行添加列之后添加默认值直接写入数据块.
Here is the projection information for column DEF_W_NULL.
 3 创建表,增加一列并指定默认值
[[email protected] ~]$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.2.0 Production on Thu Aug 24 22:26:36 2017

Copyright (c) 1982, 2014, Oracle.  All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

SQL> conn test/test@pdbcndba
Connected.
SQL> create table default_values (
   id number primary key
   );
  2    3  
Table created.

SQL> insert into default_values values (1);

1 row created.

SQL> insert into default_values values (2);

1 row created.

SQL> insert into default_values values (3);

1 row created.

SQL> insert into default_values values (4);

1 row created.

SQL> alter table default_values add def_w_null varchar2(20) default 'THIS IS DEFAULT2';

Table altered.

SQL> insert into default_values (id) values (5);

1 row created.

SQL> commit;

Commit complete.

4 通过表达式可以看到,。在添加新列之前添加ID 1 - 4,SYS_NC0000$为NULL,文件中的空值替换为元数据默认值。ID = 5之后被添加,因此它的BITVAL = 1,从我们看到的投影信息中显示,这个列显示了它是如何写入文件的。
SQL> 
SQL> col DEF_W_NULL for a20
SQL> col is_hidden_col_null for a20
SQL> col bitval for a10
SQL> col SYS_NC00002$ for a20
SQL> col SYS_NC00002$ for a10
SQL> select id, DEF_W_NULL, nvl2(SYS_NC00002$,'is not null','is null') is_hidden_col_null, SYS_NC00002$, TO_CHAR (sys_op_vecbit(SYS_NC00002$,0)) bitval  FROM default_values;

	ID          DEF_W_NULL		IS_HIDDEN_COL_NULL   SYS_NC0000 BITVAL
---------- -------------------- -------------------- ---------- ----------
	 1         THIS IS DEFAULT2	         is null
	 2         THIS IS DEFAULT2	         is null
	 3         THIS IS DEFAULT2	         is null
	 4         THIS IS DEFAULT2	         is null
	 5         THIS IS DEFAULT2	         is not null  01 	     1
5 更新id=1 的值,DEF_W_NULL不变,在DEF_W_NULL列上什么都没有发生,只更新了ID列
SQL> update default_values set id=10 where id=1;

1 row updated.

SQL> commit;

Commit complete.

SQL> select id, DEF_W_NULL, nvl2(SYS_NC00002$,'is not null','is null') is_hidden_col_null, SYS_NC00002$, TO_CHAR (sys_op_vecbit(SYS_NC00002$,0))bitval  FROM default_values;

	ID        DEF_W_NULL		IS_HIDDEN_COL_NULL   SYS_NC0000 BITVAL
---------- -------------------- -------------------- ---------- ----------
	    10 THIS IS DEFAULT2	    is null
	     2 THIS IS DEFAULT2	    is null
	     3 THIS IS DEFAULT2	    is null
	     4 THIS IS DEFAULT2	    is null
	     5 THIS IS DEFAULT2	    is not null	         01 	    1
		 
6 使用default 关键字或者默认值去更改def_w_null,Oracle更新了物理存储的值
SQL> update default_values set def_w_null=default, id=11 where id=2;

1 row updated.

SQL> update default_values set def_w_null='THIS IS DEFAULT2', id=12 where id=3;

1 row updated.

SQL> commit;

Commit complete.

SQL> select id, DEF_W_NULL, nvl2(SYS_NC00002$,'is not null','is null') is_hidden_col_null, SYS_NC00002$, TO_CHAR (sys_op_vecbit(SYS_NC00002$,0))bitval  FROM default_values;

	ID      DEF_W_NULL		    IS_HIDDEN_COL_NULL    SYS_NC0000 BITVAL
---------- -------------------- -------------------- ---------- ----------
	10         THIS IS DEFAULT2	is null
	11         THIS IS DEFAULT2	is not null	          01 	     1
	12         THIS IS DEFAULT2	is not null	          01 	     1
	 4         THIS IS DEFAULT2	is null                           
	 5         THIS IS DEFAULT2	is not null	          01 	     1

7 现在更改表元数据中的默认值,查看投影信息,它必须更新现有的行来存储旧的默认值。让我们验证。
--Oracle在表元数据中存储了两种不同的默认值——当前活动的默认值和添加列时的初始值
	 
SQL> alter table default_values modify DEF_W_NULL varchar2(20) default 'NEW DEFAULT';

Table altered.

SQL> insert into default_values (id) values (6);

1 row created.

SQL> commit;

Commit complete.

SQL> select id, DEF_W_NULL, nvl2(SYS_NC00002$,'is not null','is null') is_hidden_col_null, SYS_NC00002$, TO_CHAR (sys_op_vecbit(SYS_NC00002$,0))bitval  FROM default_values;

	ID               DEF_W_NULL	IS_HIDDEN_COL_NULL   SYS_NC0000 BITVAL
---------- -------------------- -------------------- ---------- ----------
	10         THIS IS DEFAULT2	is null
	11         THIS IS DEFAULT2	is not null	             01 	1
	12         THIS IS DEFAULT2	is not null	             01 	1
	 4         THIS IS DEFAULT2	is null                  
	 5         THIS IS DEFAULT2	is not null	             01 	1
	 6         NEW DEFAULT		is not null	             01 	1

6 rows selected.

8 多个带有空默认值的列在同一个表中,不会为新列增加隐藏列
SQL> alter table default_values add def_w_null2 varchar2(20) default 'THIS IS DEFAULT 3';

Table altered.

SQL> insert into default_values (id) values (7);

1 row created.

SQL> commit;

Commit complete.

SQL> col BITVAL1 for a10
SQL> col BITVAL2 for a10
SQL> set line 200
SQL> select id, DEF_W_NULL, nvl2(SYS_NC00002$,'is not null','is null') is_hidden_col_null, SYS_NC00002$, TO_CHAR (sys_op_vecbit(SYS_NC00002$,0))bitval1, TO_CHAR (sys_op_vecbit(SYS_NC00002$,1)) bitval2  FROM default_values where id in (6,7);

	ID        DEF_W_NULL		IS_HIDDEN_COL_NULL   SYS_NC0000 BITVAL1    BITVAL2
---------- -------------------- -------------------- ---------- ---------- ----------
	 6         NEW DEFAULT		is not null	         01 	    1	       0
	 7         NEW DEFAULT		is not null	         03 	    1	       1
                                                    
新列的对象信息:
DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00002$",1)),
  NULL,NVL("DEF_W_NULL2",'THIS IS DEFAULT 3'),
  '0',NVL("DEF_W_NULL2",'THIS IS DEFAULT 3'),
  '1',"DEF_W_NULL2")

猜你喜欢

转载自blog.csdn.net/leo__1990/article/details/90032418