Default

Lösung: Eine unerwartete Bedingung in der Where Clausel

Die merkwürdige Bedingung wird von der Datenbank automatisch generiert.
Die Ursache ist die DDL Optimization, die es in der Form seit Version 11G gibt.
Wenn man bei einer Tabelle eine zusätzliche Spalte einfügt, muss diese Spalte nicht zwingend physisch erzeugt werden.
Es kann auch eine “DDL optimized” Spalte erzeugt werden und wenn man einen Default angibt, kann diese Spalte auch not null sein.
Damit erspart die Datenbank sich den Aufwand, jeden Datensatz um eine Spalte zu erweitern.
Satt dessen wird nur ein Eintrag ins Dictionary gemacht, was natürlich viel schneller geht.
Jede Datenzeile kann einen Wert für die “DDL optimized” Spalte enthalten, wenn der Wert über einen insert eingefügt wurde.
Wenn kein Wert eingefügt wird, wird der Default Wert verwendet.
Da es möglich ist, dass kein erfasster Wert existiert, muss die Datenbank den spaltennamen durch die Formel ersetzen.
Hier eine einfaches Beispiel :

create table x (y number);
insert into x select rownum from dual connect by rownum < 1000000;
commit;
alter table x add ( z number default 1 not null);
select 1 from x where z=1;

Wenn wir uns den Execution Plan der Abfrage ansehen, bemerken wir, dass der Spaltenname Z durch die Formel


(NVL("Z",1)=1)

ersetzt wurde.

Hier noch der Link zu Carlos Blog: Interesting case where a full table scan is chosen instead of an index

Eine unerwartete Bedingung in der where Klausel

Es macht mich stolz zu erfahren, dass Carlos Sierra meinen Blog verfolgt. Carlos ist mir aus meiner Zeit bei Oracle schon lange bekannt, auch wenn wir uns erst kürzlich das erste Mal getroffen haben. Ich schätze Carlos als einen Mann der Tat. Wenn er einen Missstand sieht, beklagt er sich nicht, sondern tut etwas dagegen.
Mit meinem nächsten Beispiel will ich zeigen, dass er auch ein scharfsinniger Analytiker ist.
Vor Kurzem sah ich in einem Plan eine Bedingung, die so nicht im Sql statement stand. Ich wollte wissen, wie die Bedingung in den Plan gekommen war.
Ich gebe dazu ein einfaches Beispiel: Gegeben sei eine Tabelle x die wie folgt aussieht


SQL> desc x
Name Null? Typ
----------------------------------------- -------- -----------------
Y NUMBER
Z NOT NULL NUMBER

Ich lasse die folgende Abfrage laufen:


select count(*) from x where z=1;

Der Exection Plan sieht aus wie folgt:


Plan hash value: 989401810

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |       |       |   420 (100)|          |
|   1 |  SORT AGGREGATE    |      |     1 |    13 |            |          |
|*  2 |   TABLE ACCESS FULL| X    |  1144K|    14M|   420   (2)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(NVL("Z",1)=1)

Wieso weisst der Plan diese merkwürdige Bedingung auf? Die Antwort finded Ihr in Carlos Sierra’s Blog. Noch ein Hinweis: Es hat etwas mit Default Werten zu tun.