12c - Invisible Columns...

Posted by noreply(at)blogger.com (Thomas Kyte) on Oracle Blogs See other posts from Oracle Blogs or by noreply(at)blogger.com (Thomas Kyte)
Published on Tue, 2 Jul 2013 14:50:59 +0000 Indexed on 2013/07/02 17:10 UTC
Read the original article Hit count: 258

Filed under:
Remember when 11g first came out and we had "invisible indexes"?  It seemed like a confusing feature - indexes that would be maintained by modifications (hence slowing them down), but would not be used by queries (hence never speeding them up).  But - after you looked at them a while, you could see how they can be useful.  For example - to add an index in a running production system, an index used by the next version of the code to be introduced later that week - but not tested against the queries in version one of the application in place now.  We all know that when you add an index - one of three things can happen - a given query will go much faster, it won't affect a given query at all, or... It will make some untested query go much much slower than it used to.  So - invisible indexes allowed us to modify the schema in a 'safe' manner - hiding the change until we were ready for it.

Invisible columns accomplish the same thing - the ability to introduce a change while minimizing any negative side effects of that change.  Normally when you add a column to a table - any program with a SELECT * would start seeing that column, and programs with an INSERT INTO T VALUES (...) would pretty much immediately break (an INSERT without a list of columns in it).  Now we can add a column to a table in an invisible fashion, the column will not show up in a DESCRIBE command in SQL*Plus, it will not be returned with a SELECT *, it will not be considered in an INSERT INTO T VALUES statement.  It can be accessed by any query that asks for it, it can be populated by an INSERT statement that references it, but you won't see it otherwise.

For example, let's start with a simple two column table:

ops$tkyte%ORA12CR1> create table t
  2  ( x int,
  3    y int
  4  )
  5  /
Table created.

ops$tkyte%ORA12CR1> insert into t values ( 1, 2 );
1 row created.

Now, we will add an invisible column to it:

ops$tkyte%ORA12CR1> alter table t add 
                    ( z int INVISIBLE );
Table altered.

Notice that a DESCRIBE will not show us this column:

ops$tkyte%ORA12CR1> desc t
 Name              Null?    Type
 ----------------- -------- ------------
 X                          NUMBER(38)
 Y                          NUMBER(38)

and existing inserts are unaffected by it:

ops$tkyte%ORA12CR1> insert into t values ( 3, 4 );
1 row created.

A SELECT * won't see it either:

ops$tkyte%ORA12CR1> select * from t;

         X          Y
---------- ----------
         1          2
         3          4

But we have full access to it (in well written programs! The ones that use a column list in the insert and select - never relying on "defaults":

ops$tkyte%ORA12CR1> insert into t (x,y,z) 
                        values ( 5,6,7 );
1 row created.

ops$tkyte%ORA12CR1> select x, y, z from t;
         X          Y          Z
---------- ---------- ----------
         1          2
         3          4
         5          6          7

and when we are sure that we are ready to go with this column, we can just modify it:

ops$tkyte%ORA12CR1> alter table t modify z visible;
Table altered.

ops$tkyte%ORA12CR1> select * from t;

         X          Y          Z
---------- ---------- ----------
         1          2
         3          4
         5          6          7


I will say that a better approach to this - one that is available in 11gR2 and above - would be to use editioning views (part of Edition Based Redefinition - EBR ).  I would rather use EBR over this approach, but in an environment where EBR is not being used, or the editioning views are not in place, this will achieve much the same.

Read these for information on EBR:


© Oracle Blogs or respective owner