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.