Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Mengapa Oracle menambahkan kolom tersembunyi di sini?

Dalam rilis Oracle 11g Oracle telah memperkenalkan teknik optimasi baru untuk meningkatkan kinerja operasi DDL. Fitur baru ini memungkinkan waktu eksekusi yang sangat cepat saat menambahkan NOT NULL kolom dengan nilai default ke tabel yang ada. Sejak rilis 12c, pengoptimalan DDL telah diperluas untuk menyertakan NULL kolom yang memiliki nilai default.

Pertimbangkan tabel pengujian berikut dengan 1.000.000 baris:

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

Sekarang kita akan menambahkan kolom bukan nol ekstra yang memiliki nilai default di sesi yang berbeda untuk 11g dan 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

Perhatikan perbedaan dalam waktu eksekusi:1 juta baris diperbarui dalam 5 md!?

Rencana eksekusi menunjukkan:

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

Rencana eksekusi pada 12c menunjukkan kontras dengan 11g bagian predikat kompleks yang melibatkan kolom internal baru SYS_NC00006$ .

Predikat ini menunjukkan bahwa, secara internal, Oracle masih mempertimbangkan kolom B berpotensi dapat memuat nilai non-default. Artinya - Oracle pada awalnya tidak secara fisik memperbarui setiap baris dengan nilai default.

Mengapa kolom internal baru SYS_NC00006$ dibuat?

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              

Perhatikan perbedaan nilai B dan kolom internal terkait. Oracle hanya memeriksa melalui kolom internal yang dihasilkan sistemnya (mis. SYS_NC00006$ ) dan melalui SYS_OP_VECBIT berfungsi apakah akan mempertimbangkan nilai default kolom B atau nilai sebenarnya yang dimodifikasi melalui pernyataan DML eksplisit.

Ada apa dengan dua pernyataan alter yang terpisah?

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

Nilai kolom baru tetap NULL untuk semua baris. Tidak ada pembaruan nyata yang diperlukan oleh karena itu pernyataan DDL tidak akan dioptimalkan.

Di sini adalah artikel OTN yang menjelaskan optimasi DDL baru secara lebih rinci.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dapatkan daftar semua fungsi dan prosedur dalam database Oracle

  2. Bagaimana saya harus menangani parameter nol dalam prosedur tersimpan PL/SQL ketika saya ingin menggunakannya dalam perbandingan?

  3. Tidak dapat memasukkan karakter arab ke dalam database Oracle

  4. Bagaimana saya bisa menemukan PEMILIK objek di Oracle?

  5. kueri untuk menemukan semua kolom dalam tabel tanpa nilai di dalamnya