default 값을 포함한 컬럼 추가시 오라클 버전별 개선 사항
1. 11g 이전 버전의 경우
컬럼 추가 후 default 값으로 추가된 컬럼이 내부적으로 update가 발생한다.
만약 update 트리거가 걸려 있다면 트리거도 발동된다.
2. 11g 이후 버전의 경우
nullable 인지 아닌지 여부에 내부 작업 동작이 바뀐다.
not null 제약도 포함할 경우 내부적인 update 없이 메타데이터로 default 값이 내부에 저장이 된다.
그리고 데이터 조회시에 메타정보에서 default 값을 가져오는 구조이다.
nullable 인 경우 이전과 같은 방식으로 동작하게 된다.
아래는 이와 관련한 내용의 테스트 내용이다.
-- 테스트 데이터 생성
16:53:42 db_mon> exec dbms_application_info.set_module('db_mon','db_mon');
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
16:55:24 db_mon> CREATE TABLE col_add_test
16:55:30 2 AS
16:55:30 3 SELECT * FROM dba_objects
16:55:30 4 WHERE 1=0;
Table created.
Elapsed: 00:00:00.03
16:55:30 db_mon> BEGIN
16:55:35 2 FOR C IN 1 .. 20
16:55:35 3 LOOP
16:55:35 4 INSERT INTO col_add_test
16:55:35 5 SELECT * FROM DBA_OBJECTS;
16:55:35 6
16:55:35 7 COMMIT;
16:55:35 8 END LOOP;
16:55:35 9 END;
16:55:35 10 /
PL/SQL procedure successfully completed.
Elapsed: 00:01:01.52
|
nullable 이면서 default 값을 가지는 컬럼을 추가해 본다
16:56:37 db_mon> alter table col_add_test add (col1 varchar2(100) default 'add column test');
Table altered.
Elapsed: 00:02:07.73
16:58:55 db_mon>
|
시간이 2분 7초 소요된 것을 확인할 수 있다.
아래는 위 작업세션에 대해 세션 모니터링 한 결과이다.
16:58:45 db_mon> @kwan_mon db_mon
#### Session info ####
SID SERIAL# USERNAME MODULE TADDR
---------- ---------- ---------- -------------------- ----------------
1038 12363 DB_MON db_mon C0000003E4F865E0
1 row selected.
#### Transaction info ####
SID SERIAL# USERNAME START_TIME UNDO USED_UREC USED_UBLK LOG_IO PHY_IO CR_GET CR_CHANGE ADDR
---------- ---------- ---------- -------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------
1038 12363 DB_MON 01/16/23 16:56:47 549.57M 6739888 70345 24165792 24534 1389817 1055264 C0000003E4F865E0
1 rows selected.
16:58:54 db_mon>
|
모니터링 결과를 보면 트랜잭션이 발생하며 undo가 쌓이는 것을 확인할 수 있다.
즉, 내부적으로 update 트랜잭션이 발생한다는 것이다.
그럼, 이제 not null 이면서 default 값을 가지는 컬럼을 추가해 본다
16:58:55 db_mon> alter table col_add_test add (col2 varchar2(100) default 'add column test' not null);
Table altered.
Elapsed: 00:00:00.05
17:16:08 db_mon>
|
수행시간이 1초도 걸리지 않았다.
같은 컬럼 추가지만 not null 제약 조건을 걸면 위와 같이 내부적으로 update가 발생하지 않는다.
모니터링 해 보면 트랜잭션도 발생하지 않는 것을 확인할 수 있다.
이와 같이 11g 버전부터는 default 값을 갖는 컬럼을 추가할 때 not null 제약 조건을 걸 경우 예전과 다르게 내부적으로 update를 수행하지 않는다.
작업 시간은 줄고 내부적으로 발생하는 update로 인한 서비스 문제도 발생하지 않게 되었다.
2. 12.1c 이후 버전의 경우
11g 버전과 다르게 nullable 인 컬럼에 default를 설정하고 추가해도 빨리 끝난다.
컬럼의 default 값이 not null, nullable 두 경우 모두 메타데이터로 저장된다.
아래는 이와 관련한 테스트 내용이다.
13:22:04 DB_MON> CREATE TABLE col_add_test
2 AS
3 SELECT * FROM dba_objects
4 WHERE 1=0;
Table created.
Elapsed: 00:00:00.186
13:22:19 DB_MON> BEGIN
2 FOR C IN 1 .. 20
3 LOOP
4 INSERT INTO col_add_test
5 SELECT * FROM DBA_OBJECTS;
6
7 COMMIT;
8 END LOOP;
9 END;
10 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:12.216
13:24:06 DB_MON> alter table col_add_test add (col1 varchar2(100) default 'add column test');
Table altered.
Elapsed: 00:00:00.082
13:25:19 DB_MON> alter table col_add_test add (col2 varchar2(100) default 'add column test' not null);
Table altered.
Elapsed: 00:00:00.040
13:25:32 DB_MON>
|
not null, nullable 한 컬럼을 다 추가해 보면 시간이 유사하게 1초 미만으로 걸린다.
이와 같이 12c 버전부터는 default 값을 가지는 컬럼 추가 작업이 개선되어 부담이 줄게 되었다.
3. 결론
default 값을 갖는 컬럼을 추가할 때 관리자는 내부에서 발생하는 update 때문에 작업에 대한 부담감이 항상 많았었다.
11g 버전에서 반쪽짜리로 not null 제약 조건을 줄 경우 이런 부담감을 없애 줬는데
12c 버전에서는 모든 상황에서 부담감 없이 컬럼을 추가할 수 있도록 개선이 된 것이다.
버전이 올라가면서 이런 개선 사항들이 있어야 업그레이드 하는 맛이 있을 듯하다.
좋은 정보 감사합니다.