Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Tại sao Oracle thêm một cột ẩn ở đây?

Trong phiên bản Oracle 11g Oracle đã giới thiệu một kỹ thuật tối ưu hóa mới để cải thiện hiệu suất của các hoạt động DDL. Tính năng mới này cho phép thời gian thực thi cực kỳ nhanh chóng khi thêm NOT NULL cột có giá trị mặc định cho một bảng hiện có. Kể từ bản phát hành 12c, tối ưu hóa DDL đã được mở rộng để bao gồm NULL cột có giá trị mặc định.

Hãy xem xét bảng kiểm tra sau với 1.000.000 hàng:

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

Bây giờ chúng ta sẽ thêm một cột bổ sung không null có giá trị mặc định trong các phiên khác nhau cho 11g và 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

Nhận thấy sự khác biệt trong thời gian thực hiện:1 triệu hàng được cập nhật trong 5 mili giây !?

Kế hoạch thực hiện cho thấy:

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

Kế hoạch thực thi trên 12c hiển thị ngược lại với 11g một phần vị từ phức tạp liên quan đến cột nội bộ mới SYS_NC00006$ .

Vị từ này chỉ ra rằng, trong nội bộ, Oracle vẫn đang xem xét cột B có khả năng chứa các giá trị không mặc định. Nó có nghĩa là - Oracle lúc đầu không cập nhật vật lý từng hàng với giá trị mặc định.

Tại sao lại có cột nội bộ mới SYS_NC00006$ được tạo ra?

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              

Lưu ý sự khác biệt về giá trị của B và các cột nội bộ liên quan. Oracle chỉ đơn giản là kiểm tra thông qua cột nội bộ do hệ thống tạo ra (ví dụ:SYS_NC00006$ ) và qua SYS_OP_VECBIT chức năng xem xét giá trị mặc định của cột B hay giá trị thực được sửa đổi thông qua một câu lệnh DML rõ ràng.

Điều gì xảy ra với hai câu lệnh thay thế riêng biệt?

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

Giá trị của cột mới vẫn là NULL cho tất cả các hàng. Không cần cập nhật thực sự, do đó câu lệnh DDL sẽ không được tối ưu hóa.

Tại đây là một bài báo OTN giải thích chi tiết hơn về tối ưu hóa DDL mới.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách đảo ngược một chuỗi trong Oracle (11g) SQL mà không cần sử dụng hàm REVERSE ()

  2. Hàm NLS_LOWER () trong Oracle

  3. Xóa các thẻ HTML đơn giản khỏi Chuỗi trong Oracle thông qua RegExp, Cần giải thích

  4. ORA-01097

  5. Tạo Người dùng Oracle nếu nó chưa tồn tại