Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Dlaczego Oracle dodaje tutaj ukrytą kolumnę?

W wydaniu Oracle 11g firma Oracle wprowadziła nową technikę optymalizacji w celu poprawy wydajności operacji DDL. Ta nowa funkcja umożliwia niezwykle szybki czas wykonania po dodaniu NOT NULL kolumna z wartością domyślną do istniejącej tabeli. Od wydania 12c optymalizacja DDL została rozszerzona o NULL kolumny o wartości domyślnej.

Rozważ poniższą tabelę testową z 1 000 000 wierszy:

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); 

Teraz dodamy dodatkową kolumnę nie zerową, która ma wartość domyślną w różnych sesjach dla 11g i 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

Zwróć uwagę na różnicę w czasie wykonania:1M wierszy zaktualizowanych w 5 ms !?

Plan wykonania pokazuje:

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

Plan wykonania na 12c pokazuje w przeciwieństwie do 11g złożoną część predykatu zawierającą nową wewnętrzną kolumnę SYS_NC00006$ .

Predykat ten wskazuje, że wewnętrznie Oracle nadal uważa, że ​​kolumna B może potencjalnie zawierać wartości inne niż domyślne. Oznacza to, że Oracle na początku nie aktualizuje fizycznie każdego wiersza wartością domyślną.

Dlaczego nowa kolumna wewnętrzna SYS_NC00006$ jest tworzone?

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              

Zwróć uwagę na różnicę w wartościach B i powiązanych kolumn wewnętrznych. Oracle po prostu sprawdza w swojej wewnętrznej kolumnie generowanej przez system (np. SYS_NC00006$ ) i przez SYS_OP_VECBIT funkcja, czy brać pod uwagę domyślną wartość kolumny B, czy wartość rzeczywistą zmodyfikowaną za pomocą jawnej instrukcji DML.

Co to jest z dwoma oddzielnymi oświadczeniami alter?

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

Wartość nowej kolumny pozostaje NULL dla wszystkich wierszy. Nie są potrzebne żadne prawdziwe aktualizacje, dlatego instrukcja DDL nie zostanie zoptymalizowana.

Tu to artykuł OTN, który bardziej szczegółowo wyjaśnia nową optymalizację DDL.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. użycie wyjścia kursora w zaznaczeniu

  2. Nie można znaleźć nazwy typu lub przestrzeni nazw „oracle” błąd

  3. Dynamiczne instrukcje Select SQL z MyBatis

  4. Wyzwanie testowania bazy danych Oracle — Porównaj dane schematu

  5. Podłączanie SQL Server do Oracle