Skip to Main Content
  • Questions
  • Add NULLABLE column with DEFAULT values to a large table

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, ojock.

Asked: October 11, 2019 - 12:36 pm UTC

Last updated: October 21, 2019 - 12:13 pm UTC

Version: 11.2.0.4

Viewed 10K+ times! This question is

You Asked

I'm adding a number of columns with DEFAULT values that are NULLABLE to a large table

e.g

alter table big_table add (col1 varchar2(1) default 0, col2 varchar2(1) default 0);


It's taking a long time to do because Oracle is executing a bit of recursive SQL like this behind the scenes when the ALTER TABLE is submitted;

update big_table set col1 = '0', col2 = '0'


From experience of enabling foreign key constraint in PARALLEL, I did this;

alter session force parallel dml;
alter session force parallel query;
alter session force parallel ddl;
alter table big_table parallel;

-- now do my foreign key constraints => first enable novalidate, then validate

alter table big_table noparallel;


The above works and forces the recursive SQL that Oracle executes when validating the FK constraint to be executed in PARALLEL.

However, applying the same approach I had used for enabling FK constraint in PARALLEL to adding NULLABLE columns with DEFAULT values - it's not working, the recursive UPDATE above is refusing to go PARALLEL (even though the execution PLAN is showing PARALLEL).

Am I missing a "trick" ? Or has this improved in a later version of Oracle, 12c onwards,etc ?

If I can get that recursive UPDATE to go PARALLEL, I know then the ALTER will be much quicker, because as a separate test, I ran that UPDATE standalone in PARALLEL, and it did go PARALLEL and completed very quickly.

All statistics are up to date.

and Chris said...

Can you make the column mandatory when you add it, to take advantage of fast column add. Then make it nullable later?

alter table big_table add ( 
  col1 varchar2(1) default 0 not null, 
  col2 varchar2(1) default 0 not null
);

alter table t 
  modify ( col1 null, col2 null );

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Nullable might be possible

ojock, October 11, 2019 - 2:31 pm UTC

Yes, that is something I tried, but you get the same performance hit when you make it "NULLABLE" later.
Connor McDonald
October 21, 2019 - 12:13 pm UTC

Time to upgrade I think :-) 12.2 and above will give you this

SQL> create table t as select d.* from dba_objects d, ( select 1 from dual connect by level <= 50 );

Table created.

SQL> set timing on
SQL> alter table t add xxx int default 0 not null;

Table altered.

Elapsed: 00:00:00.00
SQL> alter table t add xxx1 int default 0;

Table altered.

Elapsed: 00:00:00.00


More to Explore

SQL

The Oracle documentation contains a complete SQL reference.