Monday, July 26, 2010

New Add Column Functionality - 11g New Features

Prior to Oracle 11g, when you add a column with not null constraint and with a default value, Oracle actually populates the value in all the rows of the table. All the rows, ouch! Imagine a multimillion-row table where the data will be updated several million times and how much redo and undo it will generate. In addition, it will also lock the table for the entire duration preventing DDLs. This caused a lot of consternation among users.But In Oracle 11g, this is handled different.

Ran the script in 9iR2, 10gR2 and 11gR1 and Tkprof show's the below results.

create table T nologging
as
select *
from all_objects;

alter session set timed_statistics=true;
alter session set events '10046 trace name context forever, level 16';
alter table T add grade varchar2(1) default 'x' not null;

Oracle - 9iR2
********************************************************************************

alter table t add grade varchar2(1) default 'x' not null


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.01          0          0          0           0
Execute      0      0.00       0.00          0          0          0           0
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        1      0.00       0.01          0          0          0           0

Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: 107 
********************************************************************************

update "T" set "GRADE"='x'


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.22          0          0          0           0
Execute      1      1.35       1.95        452        459      33914       33243
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      1.35       2.18        452        459      33914       33243

Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: 107     (recursive depth: 1)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  UPDATE 
  33243   TABLE ACCESS FULL T
********************************************************************************

Oracle -10gR2
********************************************************************************

alter table t add grade varchar2(1) default 'x' not null


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.01       0.04          0          0          0           0
Execute      1      0.01       0.30          0          1          2           0
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.03       0.35          0          1          2           0

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 54
********************************************************************************

update "T" set "GRADE"='x'


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          1          0           0
Execute      1      3.21       5.51        548       2228     304319       56172
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      3.21       5.51        548       2229     304319       56172

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 54     (recursive depth: 1)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  UPDATE  T (cr=1598 pr=95 pw=0 time=3176654 us)
 159118   TABLE ACCESS FULL T (cr=2220 pr=548 pw=0 time=1113963 us)
********************************************************************************

Oracle - 11gR1
********************************************************************************

SQL ID : dpj1atuacv8zx
alter table t add grade varchar2(1) default 'x' not null


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          1         25           0
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.00       0.01          0          1         25           0

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 81 
********************************************************************************

looking at the 11g Trace File I could not see a reference to the UPDATE T...Statement This behavior results in significantly less redo and undo, and also completes faster.

4 comments:

  1. Which version of 11g? I see in 11gR1.

    update "DUMMY_TAB" set "PRIORITY_GROUP"=1

    call count cpu elapsed disk query current rows
    ------- ------ -------- ---------- ---------- ---------- ---------- ----------
    Parse 1 0.00 0.00 0 1 0 0
    Execute 1 128.98 169.06 79978 109961 4075558 1973227
    Fetch 0 0.00 0.00 0 0 0 0
    ------- ------ -------- ---------- ---------- ---------- ---------- ----------
    total 2 128.99 169.06 79978 109962 4075558 1973227

    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 180 (recursive depth: 1)

    Rows Row Source Operation
    ------- ---------------------------------------------------
    0 UPDATE DUMMY_TAB (cr=111092 pr=79978 pw=0 time=0 us)
    1973227 PX COORDINATOR (cr=109874 pr=42226 pw=0 time=173927 us)
    1973227 PX SEND QC (RANDOM) :TQ10000 (cr=109874 pr=42226 pw=0 time=154567 us cost=8337 size=21636615 card=1664355)
    1973227 PX BLOCK ITERATOR (cr=109874 pr=42226 pw=0 time=142461 us cost=8337 size=21636615 card=1664355)
    1973227 TABLE ACCESS FULL DUMMY_TAB (cr=109874 pr=42226 pw=0 time=128779 us cost=8337 size=21636615 card=1664355)

    ********************************************************************************

    ReplyDelete
  2. @Anonymous

    I tried this in 11.1.0.6.0. Here is the Test case.

    create table T
    as
    select *
    from emp;

    alter table T add y number default 5 not null;

    When I ran this in 10GR2 database, It shows me this. ( ALTER statement and then UPDATE )

    alter table T add y number default 5 not null

    call count cpu elapsed disk query current rows
    ------- ------ -------- ---------- ---------- ---------- ---------- ----------
    Parse 1 0.00 0.00 0 0 0 0
    Execute 1 0.01 0.04 0 1 2 0
    Fetch 0 0.00 0.00 0 0 0 0
    ------- ------ -------- ---------- ---------- ---------- ---------- ----------
    total 2 0.01 0.04 0 1 2 0

    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100

    Elapsed times include waiting on following events:
    Event waited on Times Max. Wait Total Waited
    ---------------------------------------- Waited ---------- ------------
    log file sync 1 0.01 0.01
    SQL*Net message to client 1 0.00 0.00
    SQL*Net message from client 1 0.00 0.00

    update "T" set "Y"=5


    call count cpu elapsed disk query current rows
    ------- ------ -------- ---------- ---------- ---------- ---------- ----------
    Parse 1 0.00 0.00 0 1 0 0
    Execute 1 0.00 0.00 0 3 15 14
    Fetch 0 0.00 0.00 0 0 0 0
    ------- ------ -------- ---------- ---------- ---------- ---------- ----------
    total 2 0.00 0.00 0 4 15 14

    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100 (recursive depth: 1)

    Rows Row Source Operation
    ------- ---------------------------------------------------
    0 UPDATE T (cr=3 pr=0 pw=0 time=341 us)
    14 TABLE ACCESS FULL T (cr=3 pr=0 pw=0 time=67 us)


    But in 11GR1, I see only ALTER and **NO** UPDATE statement.

    alter table T add y number default 5 not null


    call count cpu elapsed disk query current rows
    ------- ------ -------- ---------- ---------- ---------- ---------- ----------
    Parse 1 0.00 0.03 0 0 0 0
    Execute 1 0.00 0.09 0 3 26 0
    Fetch 0 0.00 0.00 0 0 0 0
    ------- ------ -------- ---------- ---------- ---------- ---------- ----------
    total 2 0.00 0.13 0 3 26 0

    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 91

    Elapsed times include waiting on following events:
    Event waited on Times Max. Wait Total Waited
    ---------------------------------------- Waited ---------- ------------
    log file sync 1 0.00 0.00
    SQL*Net message to client 1 0.00 0.00
    SQL*Net message from client 1 0.00 0.00

    Can you rerun this testcase as such and report me back?

    create table T
    as
    select *
    from emp;

    alter table T add y number default 5 not null;

    ReplyDelete
  3. Hi Rajesh,

    Thanks for your prompt response.

    You could be right with 11.1.0.6. But I don't have any of the versions that you mentioned and I have only 11.1.0.7 with lots of patches.

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

    See if you can test it with this version.

    Thanks anyway and I believe you. Just I want to know which version it's working, as this is very nice feature to have.

    ReplyDelete
  4. I figured out the issue. It's because of the blob column.

    ReplyDelete