10g vs 11g add a column with not null default value

March 8th, 2011 | Posted in 10g, 11gR2, Blog | 1 Comment


Introduction:
Prior to Oracle database 11g, adding a new column with a default NOT NULL value were a challenge. Especially, when the concerned table contains thousands or millions of records. Oracle 10g updates ALL the rows of the concerned table with the new default value. In my busy real time OLTP databases, I had to create another intermediate table with the same structure plus the new default not null column. This solution needs a switch to the second table and a rename table operation.
As you can Imagine, this solution takes time, resources, space, loads, locks.
Oracle database 11g offers a new quick, easy, instant solution; instead of updating ALL the rows of the table, Oracle 11g now updates the metadata only.

The process of adding the new column with a default NOT NULL value is now much more easy, and faster.
In the following section, we will compare this process between an Oracle 10g release 2 database and an Oracle 11g release 2 database.

Adding the new column with a default NOT NULL in 10g
In this section, we will create 2 different sessions (session1 and session2).

SESSION1:

C:\Documents and Settings\Wiss>sqlplus /nolog

SQL*Plus: Release 10.2.0.1.0 - Production on Mar Mar 8 10:44:28 2011

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

SQL> connect sys as sysdba

Introduzca la contrase±a:

Conectado.

SQL> select * from v$version;

BANNER

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

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE    10.2.0.1.0      Production

TNS for 32-bit Windows: Version 10.2.0.1.0 - Production

NLSRTL Version 10.2.0.1.0 - Production

SQL> create table sales as

  2  select rownum as id,

  3  mod(rownum,5) as product_id,

  4  mod(rownum,100) as client_id,

  5  2000 as price,

  6  to_date(

  7  '01.'||lpad(to_char(mod(rownum,3)+1),2,'0')||'.2011','dd.mm.yyyy')

  8  as c_date

  9  from dual

 10  connect by level <= 2.5e5;

Tabla creada.

SQL> set timi on

SQL> select count(*) from sales;

  COUNT(*)

----------

    250000

Transcurrido: 00:00:00.70

SQL>

SESSION2:


C:\Documents and Settings\Wiss>sqlplus /nolog

SQL*Plus: Release 10.2.0.1.0 - Production on Mar Mar 8 11:00:59 2011

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

SQL> connect sys as sysdba

Introduzca la contrase±a:

Conectado.

SQL> set timi on

SQL> desc sales;

 Nombre                                    +Nulo?   Tipo

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

 ID                                                 NUMBER

 PRODUCT_ID                                         NUMBER

 CLIENT_ID                                          NUMBER

 PRICE                                              NUMBER

 C_DATE                                             DATE

SQL> select count(*) from sales;

  COUNT(*)

----------

    250000

Transcurrido: 00:00:00.04

In the session1 we set the event 10046 to analyse deeply the process of adding a column with default NOT NULL value in sales table:

SQL> alter session set events '10046 trace name context forever,

  2  level 16';

SesiŸn modificada.

Transcurrido: 00:00:00.00

SQL> alter table sales add (provider_id NUMBER(2) default '0' NOT NULL);

Tabla modificada.

Transcurrido: 00:01:09.42

SQL> alter session set events '10046 trace name context off';

SesiŸn modificada.

Transcurrido: 00:00:00.00

SQL>

During the execution of the alter table command, I issued the following command in the session2. The simple count all the rows of the table now takes 01min:06s.54ms, when it first took only 4ms. This is because the table was locked for update all the rows of sales table.
Also note that alter table command took 00:01min:09s.42ms.


--During alter table command

SQL> select count(*) from sales;

  COUNT(*)

----------

    250000

Transcurrido: 00:01:06.54

SQL>

We analyse the trace file generated in the USER_DUMP_DEST directory, we see these lines: (with UPDATE SALES operation)

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

PARSING IN CURSOR #5 len=37 dep=1 uid=0 oct=6 lid=0 tim=5763158610 hv=3800351085 ad='2091018c'

update "SALES" set "PROVIDER_ID"='0' 

END OF STMT

PARSE #5:c=0,e=1101,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=5763158602

*** 2011-03-08 11:18:25.218

EXEC #5:c=30046875,e=31481436,p=925,cr=930,cu=254807,mis=0,r=250000,dep=1,og=4,tim=5794641561

STAT #5 id=1 cnt=0 pid=0 pos=1 obj=0 op='UPDATE  SALES (cr=930 pr=925 pw=0 time=31481367 us)'

STAT #5 id=2 cnt=250000 pid=1 pos=1 obj=52550 op='TABLE ACCESS FULL SALES (cr=930 pr=925 pw=0 time=1294122 us)'

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

Adding the new column with a default NOT NULL in 11g
In this section too, we will create 2 different sessions (session1 and session2).

SESSION 1


SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE	11.2.0.1.0	Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

SQL> ---session1
SQL> create table sales as
  2  select rownum as id,
  3  mod(rownum,5) as product_id,
  4  mod(rownum,100) as client_id,
  5  2000 as price,
  6  to_date(
  7  '01.'||lpad(to_char(mod(rownum,3)+1),2,'0')||'.2011','dd.mm.yyyy')
  8  as c_date
  9  from dual
 10  connect by level <= 2.5e5;

Table created.

SQL> set timi on
SQL> select count(*) from sales;

  COUNT(*)
----------
    250000

Elapsed: 00:00:00.04
SQL> alter session set events '10046 trace name context forever,
  2  level 16';

Session altered.

Elapsed: 00:00:00.02
SQL> alter table sales add (provider_id NUMBER(2) default '0' NOT NULL);

Table altered.

Elapsed: 00:00:00.21
SQL> alter session set events '10046 trace name context off';

Session altered.

Elapsed: 00:00:00.00

SESSION2

SQL> ---session2
SQL> set timi on
SQL> --- Before issue the Alter table statement
SQL> select count(*) from sales;

  COUNT(*)
----------
    250000

Elapsed: 00:00:00.02
SQL> --During alter table command
SQL> select count(*) from sales;

  COUNT(*)
----------
    250000

Elapsed: 00:00:00.02
SQL>

From above, note that the alter table statement is much more faster in 11g than in 10g.
It only takes 21ms in my 11g case, whereas it took more than 1min in my 10g case.
Also, note that during the alter table operation, the session2 has the resources available to query the table.
When, we analyse the trace file in USER_DUMP_DEST (in 11g diagnostic_dest parameter), we can see there is NO more an “UPDATE SALES” statement in the trace file. Thus, because now during the add column operation Oracle stores the default value as a metadata, no more updates in the rows.

Scridb filter


One Comment to “10g vs 11g add a column with not null default value”

  1. admin says:

    Thanks for sharing new Oracle 11 g feature
    Posted by German Chernomaz


Leave a Comment





Subscribe


Polls

which oracle topic interests you most?

View Results

Loading ... Loading ...


Oracle Class Tweets


Recent Posts


Recent Comments

  • Jaspreet: Brilliant explanation.
  • Yousuf: Very Nice… Just wanted to check you have done all patching at Node 1 only.. is there any thing need to...
  • Yousuf: Very Nice.. Thanks for sharing.. Once question.. You have executed all commands on Node 1 only.. Is there any...
  • Emir: Thanks… Great article
  • borse firmate: Thank you for another informative blog. The place else may just I am getting that kind of information...
  • leandro: why this parameter is systemwide? could you read from a asm instance from one failure group and from the...
  • Mohammad: paul, we create pfile from target database to source database and later we change database name, and...
  • Muhammad Ikram: Thanks Brother for sharing pearls of knowledge. May ALLAH reward you for this both here and...
  • rgrover: Thanks for the POST. I recently encounter similar issue. Your POST helped.
  • gopalredy: really its very use full to dbas
  • Vivian: This is awesome! Thank you so much!
  • henry zhong: CDB=DB, and PDB=SCHEMA but in a sub dictionary?
  • Dehbashee: Salam Brother, Thanx for sharing, however, i would be interested in chaging the password for the grid user...
  • wissem: No we don’t need that :) Just the scripts I posted above
  • Md. Tanweer: Thanks for posting the material. I really appreciate if you can send me, if you have tutorial for 11g...
  • christiaan: Thanks!! This has been bugging the hell out of me for so long.
  • Rajasekhar: Thank you
  • Samarjit Panigrahy: Very Nice and Simple Demo… Cool :)
  • cq: Any reason not to use auto patch for both CRS and RAC homes with one command? Or use opatch auto for RAC home as...
  • Hitesh: Hi, Can we use this RACcheck tool on oracle SE version ? Thanks