Dienstag, April 01, 2014

Add Column DDL-Optimierung in 11g

Im OTN-Forum wurde heute ein Feature erwähnt, das mir bisher entgangen war (oder das ich schon wieder vergessen hatte): das Hinzufügen einer Spalte mit Default-Wert und NOT NULL Constraint kann ohne Update der betroffenen Datensätze durchgeführt werden und erfordert als reine Metadaten-Anpassung nur sehr wenig Zeit. Ohne den NOT NULL Constraint muss hingegen jeder einzelne Datensatz aktualisiert werden, was sehr lange Laufzeiten hervorruft. In 12c ist inzwischen auch die Variante ohne den NOT NULL Constraint optimiert. Ein (von Mohamed Houri ergänzter) Blick auf die Ausführungspläne von Queries, die über eine solche Spalte einschränken, zeigt ein NVL-Prädikat, das die vorhandenen NULL-Werte in den default-Wert umwandelt - aufgrund des Constraints kann die Spalte ja keine "echten" NULL-Werte enthalten, so dass das Verfahren damit keine Probleme haben kann. In 12c ist dieses ergänzte Prädikat im Plan nicht mehr sichtbar, aber im CBO-Trace kann man die Unterschiede erkennen:

-- 12.1.0.1
-- dbms_xplan.display for both queries

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
Plan hash value: 3474700848
 
----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |    13 |     5   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |       |     1 |    13 |            |          |
|*  2 |   TABLE ACCESS FULL| TBL_1 |    10 |   130 |     5   (0)| 00:00:01 |
----------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("COL_4"=100)
 

-- event 10053 with NOT NULL constraint for col_4

============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id  | Operation           | Name    | Rows  | Bytes | Cost  | Time      |
--------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT    |         |       |       |     5 |           |
| 1   |  SORT AGGREGATE     |         |     1 |    13 |       |           |
| 2   |   TABLE ACCESS FULL | TBL_1   |    10 |   130 |     5 |  00:00:01 |
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter(NVL("COL_4",100)=100)


-- event 10053 without NOT NULL constraint for col_4

============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id  | Operation           | Name    | Rows  | Bytes | Cost  | Time      |
--------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT    |         |       |       |     5 |           |
| 1   |  SORT AGGREGATE     |         |     1 |    13 |       |           |
| 2   |   TABLE ACCESS FULL | TBL_1   |    10 |   130 |     5 |  00:00:01 |
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter(DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00003$",0)),NULL,NVL("COL_4",100),'0',NVL("COL_4",100),'1',"COL_4")=100)

Offenbar wird im Fall der ergänzten Spalte ohne NOT NULL constraint eine zusätzliche virtuelle Spalte vom Typ RAW ergänzt, deren Inhalt gesetzt wird, so bald in col_4 ein veränderter Wert eingetragen wird - und über die SYS_OP_VECBIT function (die Jared Still gelegentlich erwähnt: "Return the value of the bit at position N in a raw value" - aber sie ist natürlich nicht offiziell dokumentiert) kann bestimmt werden, ob in der Spalte ein Wert zu finden ist: also ein Update nach der initialen Definition der Spalte erfolgte.

Keine Kommentare:

Kommentar veröffentlichen