Ve verzi Oracle 11g Oracle zavedl novou optimalizační techniku pro zlepšení výkonu DDL operací. Tato nová funkce umožňuje extrémně rychlou dobu provádění při přidání NOT NULL sloupec s výchozí hodnotou do existující tabulky. Od verze 12c byla optimalizace DDL rozšířena o NULL sloupce s výchozí hodnotou.
Zvažte následující testovací tabulku s 1 000 000 řádky:
sql> create table xxy
as select rownum a from dual connect by level <= 1e6
;
sql> select /*+ gather_plan_statistics */ count(1) from xxy;
sql> select * from table(dbms_xplan.display_cursor);
Nyní přidáme další nenulový sloupec s výchozí hodnotou v různých relacích pro 11g a 12c:
11g> alter table xxy add b number default 1;
--Table XXY altered. Elapsed: 00:01:00.998
12c> alter table xxy add b number default 1;
--Table XXY altered. Elapsed: 00:00:00.052
Všimněte si rozdílu v době provádění:1M řádků aktualizováno za 5 ms!?
Prováděcí plán ukazuje:
11g> select count(1) from xxy where b = 1;
COUNT(1)
----------
1000000
11g> select * from table(dbms_xplan.display_cursor);
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1040 (100)| |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
|* 2 | TABLE ACCESS FULL| XXY | 898K| 11M| 1040 (1)| 00:00:13 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("B"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
12c> select count(1) from xxy where b = 1;
12c> select * from table(dbms_xplan.display_cursor);
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 429 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| XXY | 1000K| 4882K| 429 (2)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00002$",0)),NULL,NVL("
B",1),'0',NVL("B",1),'1',"B")=1)
Note
-----
- statistics feedback used for this statement
Prováděcí plán na 12c ukazuje na rozdíl od 11g složitou predikátovou část obsahující nový interní sloupec SYS_NC00006$
.
Tento predikát naznačuje, že Oracle interně stále zvažuje sloupec B jako potenciálně schopný obsahovat jiné než výchozí hodnoty. To znamená - Oracle nejprve fyzicky neaktualizuje každý řádek s výchozí hodnotou.
Proč nový interní sloupec SYS_NC00006$
je vytvořen?
12c> select column_name, virtual_column, hidden_column, user_generated
from user_tab_cols
where table_name = 'XXY'
;
COLUMN_NAME VIR HID USE
---------------- --- --- ---
B NO NO YES
SYS_NC00002$ NO YES NO
A NO NO YES
12c> select a, b, SYS_NC00002$ hid from xxy where a in (1,10);
A B HID
---------- ---------- ----------------
1 1
10 1
12c> update xxy set b=1 where a=10 and b=1;
1 row updated.
12c> select a, b, SYS_NC00002$ hid from xxy where a in (1,10);
A B HID
---------- ---------- ----------------
1 1
10 1 01
Všimněte si rozdílu v hodnotách B a souvisejících interních sloupcích. Oracle jednoduše kontroluje svůj interní sloupec vygenerovaný systémem (např. SYS_NC00006$
) a prostřednictvím SYS_OP_VECBIT
zda se má vzít v úvahu výchozí hodnota sloupce B nebo reálná hodnota upravená pomocí explicitního příkazu DML.
Co je to se dvěma samostatnými alter prohlášeními?
12c> alter table xxy add (b integer);
12c> alter table xxy modify b default 1;
12c> select count(b), count(coalesce(b,0)) nulls from xxy where b = 1 or b is null;
COUNT(B) NULLS
---------- ----------
0 1000000
Hodnota nového sloupce zůstává NULL pro všechny řádky. Nejsou potřeba žádné skutečné aktualizace, proto příkaz DDL nebude optimalizován.
Zde je článek OTN, který podrobněji vysvětluje novou optimalizaci DDL.