프린트 하기 URL 복사

OS 환경 : Oracle Linux 9.6 (64bit)

 

DB 환경 : Oracle AI Database 23.26.3.0.0 ai

 

방법 : 오라클 26ai MULTI_APPEND, NO_MULTI_APPEND 힌트 테스트

오라클 26ai 버전부터 Direct Path Insert 수행 후 트랜잭션을 종료하지 않아도 동일한 테이블을 다시 조회하거나 DML, Direct Path Insert를 수행할 수 있음

 

기존 19c에서는 APPEND 힌트를 사용하여 Direct Path Insert를 수행한 경우 COMMIT 또는 ROLLBACK 전 해당 테이블을 다시 조회하거나 수정하면 ORA-12838 에러가 발생했음

 

26ai에서는 이러한 제약이 기본적으로 해제되어 있음
이 기능은 _online_direct_load 히든 파라미터로 제어됨
이 파라미터를 0으로 변경하면 기능이 이전 버전처럼 동작함(append insert 후 재 append insert 안됨)
참고 : 오라클 26ai 신기능 Direct Load(Direct Path Insert) 에 대한 제약 해제 ( https://positivemh.tistory.com/1127 )

 

_online_direct_load 히든 파라미터와 더불어 본문에서 테스트 하는 NO_MULTI_APPEND 힌트를 사용하면
26ai에서도 기존 버전과 동일하게 Direct Path Insert 이후 해당 테이블을 다시 조회하거나 수정할 때 ORA-12838 에러가 발생함

 

 

테스트
1. MULTI_APPEND 힌트 확인
2. 테스트 환경 확인
3. 샘플 테이블 생성
4. APPEND 기본 동작 테스트
5. APPEND + MULTI_APPEND 테스트
6. APPEND + NO_MULTI_APPEND 테스트
7. NOAPPEND와 비교
8. 결론

 

 

테스트
1. MULTI_APPEND 힌트 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SQL>
set lines 200 pages 1000
col name for a30
col inverse for a30
col version for a15
select name, inverse, target_level, version
from v$sql_hint
where name in ('APPEND', 'NOAPPEND', 
'MULTI_APPEND', 'NO_MULTI_APPEND')
order by name;
 
NAME                           INVERSE                        TARGET_LEVEL VERSION
------------------------------ ------------------------------ ------------ ---------------
APPEND                         NOAPPEND                                  1 8.1.0
MULTI_APPEND                   NO_MULTI_APPEND                           1 23.1.0
NOAPPEND                       APPEND                                    1 8.1.0
NO_MULTI_APPEND                MULTI_APPEND                              1 23.1.0

23 버전(26ai)에 존재함

 

 

2. 테스트 환경 확인
db 버전 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SQL>
set lines 200 pages 1000
select * from v$version;
 
BANNER
---------------------------------------------------------------------------------------------------------------------------------
BANNER_FULL
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
BANNER_LEGACY                                                                                                                         CON_ID
--------------------------------------------------------------------------------------------------------------------------------- ----------
Oracle AI Database 26ai Enterprise Edition Release 23.26.3.0.0 - Production
Oracle AI Database 26ai Enterprise Edition Release 23.26.3.0.0 - Production
Version 23.26.3.0.0
Oracle AI Database 26ai Enterprise Edition Release 23.26.3.0.0 - Production                                                                0

23.26.3 버전임

 

 

COMPATIBLE 파라미터 확인

1
2
3
4
5
6
SQL> show parameter compatible
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
compatible                           string      23.6.0
noncdb_compatible                    boolean     FALSE

23.6.0임

 

 

3. 샘플 테이블 생성

1
2
3
SQL>
drop table emp2 purge;
create table emp2 as select * from emp;

 

 

데이터 건수 확인

1
2
3
4
5
SQL> select count(*) from emp2;
 
  COUNT(*)
----------
        14

현재 14건의 데이터가 존재함

 

 

4. APPEND 기본 동작 테스트
실행계획 확인을 위해 statistics_level 파라미터 all로 변경

1
2
3
SQL> alter session set statistics_level = all;
 
Session altered.

 

 

26ai에서 별도의 MULTI_APPEND 힌트 없이 기존 APPEND 힌트만 사용

1
2
3
SQL> insert /*+ append */ into emp2 select * from emp2;
 
14 rows created.

14건이 추가되어 총 28건이 됨

 

 

COMMIT 하지 않은 상태에서 바로 실행계획 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
SQL> SELECT * FROM DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST -rows -Projection +HINT_REPORT +outline');
 
Plan hash value: 1283500778
 
------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name | Starts | A-Rows |   A-Time   | Buffers | Writes |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                 |      |      1 |      0 |00:00:00.01 |      13 |      1 |       |       |          |
|   1 |  LOAD AS SELECT                  | EMP2 |      1 |      0 |00:00:00.01 |      13 |      1 |  1043K|  1043K| 1043K (0)|
|   2 |   OPTIMIZER STATISTICS GATHERING |      |      1 |     14 |00:00:00.01 |       3 |      0 |   256K|   256K|          |
|   3 |    TABLE ACCESS FULL             | EMP2 |      1 |     14 |00:00:00.01 |       2 |      0 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('23.1.0')
      DB_VERSION('23.1.0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      OUTLINE_LEAF(@"INS$1")
      LOAD_METHOD(@"INS$1" "EMP2"@"INS$1" HIGH_WATER_MARK)
      LOAD_TYPE(@"INS$1" "EMP2"@"INS$1" SERIAL)
      FULL(@"INS$1" "EMP2"@"INS$1")
      FULL(@"SEL$1" "EMP2"@"SEL$1")
      END_OUTLINE_DATA
  */
 
 
33 rows selected.

LOAD AS SELECT 실행계획이 나오고 outline data 부분에 LOAD_METHOD(HIGH_WATER_MARK)가 나온것을 보고 append 힌트가 제대로 동작했음을 알수 있음

 

 

COMMIT 하지 않고 EMP2 테이블 조회

1
2
3
4
5
SQL> select count(*) from emp2;
 
  COUNT(*)
----------
        28

정상적으로 28건이 조회됨

 

 

기존 19c에서는 이 시점에 ORA-12838 에러가 발생하지만
26ai에서는 정상적으로 조회됨
참고 : 오라클 26ai 신기능 Direct Load(Direct Path Insert) 에 대한 제약 해제 ( https://positivemh.tistory.com/1127 )

 

 

COMMIT 하지 않고 APPEND 재수행

1
2
3
SQL> insert /*+ append */ into emp2 select * from emp2;
 
28 rows created.

정상적으로 28건이 추가됨

 

 

다시 조회

1
2
3
4
5
SQL> select count(*) from emp2;
 
  COUNT(*)
----------
        56

총 56건이 정상적으로 조회됨

 

 

26ai에서는 APPEND 힌트만 사용한 경우 하나의 트랜잭션 내에서 Direct Path Insert 후 조회 및 Insert 재수행이 가능함

 

 

테스트 데이터 원복

1
2
3
SQL> rollback;
 
Rollback complete.

 

 

5. APPEND + MULTI_APPEND 사용
실행계획 확인을 위해 statistics_level 파라미터 all로 변경

1
2
3
SQL> alter session set statistics_level = all;
 
Session altered.

 

 

이번에는 APPEND 힌트와 MULTI_APPEND 힌트를 같이 사용해봄

1
2
3
SQL> insert /*+ append multi_append */ into emp2 select * from emp2;
 
14 rows created.

 

 

COMMIT 하지 않은 상태에서 바로 실행계획 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
SQL> SELECT * FROM DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST -rows -Projection +HINT_REPORT +outline');
 
Plan hash value: 1283500778
 
------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name | Starts | A-Rows |   A-Time   | Buffers | Writes |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                 |      |      1 |      0 |00:00:00.01 |      45 |      1 |       |       |          |
|   1 |  LOAD AS SELECT                  | EMP2 |      1 |      0 |00:00:00.01 |      45 |      1 |  1043K|  1043K| 1043K (0)|
|   2 |   OPTIMIZER STATISTICS GATHERING |      |      1 |     14 |00:00:00.01 |       8 |      0 |   256K|   256K|          |
|   3 |    TABLE ACCESS FULL             | EMP2 |      1 |     14 |00:00:00.01 |       7 |      0 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('23.1.0')
      DB_VERSION('23.1.0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      OUTLINE_LEAF(@"INS$1")
      LOAD_METHOD(@"INS$1" "EMP2"@"INS$1" HIGH_WATER_MARK)
      LOAD_TYPE(@"INS$1" "EMP2"@"INS$1" SERIAL)
      FULL(@"INS$1" "EMP2"@"INS$1")
      FULL(@"SEL$1" "EMP2"@"SEL$1")
      END_OUTLINE_DATA
  */
 
 
33 rows selected.

동일하게 LOAD AS SELECT 실행계획이 나오고 outline data 부분에 LOAD_METHOD(HIGH_WATER_MARK)가 나온것을 보고 append 힌트가 제대로 동작했음을 알수 있음
LOAD_METHOD, LOAD_TYPE 힌트 부분이 append 힌트만 사용했을때와 동일함

 

 

COMMIT 하지 않고 EMP2 테이블 조회

1
2
3
4
5
SQL> select count(*) from emp2;
 
  COUNT(*)
----------
        28

정상적으로 28건이 조회됨

 

 

기존 19c에서는 이 시점에 ORA-12838 에러가 발생하지만
26ai에서는 정상적으로 조회됨
참고 : 오라클 26ai 신기능 Direct Load(Direct Path Insert) 에 대한 제약 해제 ( https://positivemh.tistory.com/1127 )

 

 

COMMIT 하지 않고 APPEND MULTI_APPEND 재수행

1
2
3
SQL> insert /*+ append multi_append */ into emp2 select * from emp2;
 
28 rows created.

정상적으로 28건이 추가됨

 

 

다시 조회

1
2
3
4
5
SQL> select count(*) from emp2;
 
  COUNT(*)
----------
        56

총 56건이 정상적으로 조회됨

 

 

26ai에서는 APPEND 힌트와 MULTI_APPEND 힌트를 사용한 경우 하나의 트랜잭션 내에서 Direct Path Insert 후 조회 및 Insert 재수행이 가능함

 

 

테스트 데이터 원복

1
2
3
SQL> rollback;
 
Rollback complete.

 

 

6. APPEND + NO_MULTI_APPEND 테스트
실행계획 확인을 위해 statistics_level 파라미터 all로 변경

1
2
3
SQL> alter session set statistics_level = all;
 
Session altered.

 

 

이번에는 APPEND 힌트와 NO_MULTI_APPEND 힌트를 같이 사용해봄

1
2
3
SQL> insert /*+ append no_multi_append */ into emp2 select * from emp2;
 
14 rows created.

 

 

COMMIT 하지 않은 상태에서 바로 실행계획 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
SQL> SELECT * FROM DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST -rows -Projection +HINT_REPORT +outline');
 
Plan hash value: 1283500778
 
------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name | Starts | A-Rows |   A-Time   | Buffers | Writes |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                 |      |      1 |      0 |00:00:00.01 |      13 |      1 |       |       |          |
|   1 |  LOAD AS SELECT                  | EMP2 |      1 |      0 |00:00:00.01 |      13 |      1 |  1043K|  1043K| 1043K (0)|
|   2 |   OPTIMIZER STATISTICS GATHERING |      |      1 |     14 |00:00:00.01 |       8 |      0 |   256K|   256K|          |
|   3 |    TABLE ACCESS FULL             | EMP2 |      1 |     14 |00:00:00.01 |       7 |      0 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('23.1.0')
      DB_VERSION('23.1.0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      OUTLINE_LEAF(@"INS$1")
      LOAD_METHOD(@"INS$1" "EMP2"@"INS$1" HIGH_WATER_MARK)
      LOAD_TYPE(@"INS$1" "EMP2"@"INS$1" SERIAL)
      FULL(@"INS$1" "EMP2"@"INS$1")
      FULL(@"SEL$1" "EMP2"@"SEL$1")
      END_OUTLINE_DATA
  */
 
 
33 rows selected.

동일하게 LOAD AS SELECT 실행계획이 나오고 outline data 부분에 LOAD_METHOD(HIGH_WATER_MARK)가 나온것을 보고 append 힌트가 제대로 동작했음을 알수 있음
LOAD_METHOD, LOAD_TYPE 힌트 부분이 append 힌트만 사용했을때와 동일함

 

 

COMMIT 하지 않고 EMP2 테이블 조회

1
2
3
4
5
6
SQL> select count(*) from emp2;
select count(*) from emp2
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying it in parallel
Help: https://docs.oracle.com/error-help/db/ora-12838/

19c 환경처럼 에러가 발생함

 

 

COMMIT 하지 않고 APPEND NO_MULTI_APPEND 재수행

1
2
3
4
5
6
SQL> insert /*+ append no_multi_append */ into emp2 select * from emp2;
insert /*+ append no_multi_append */ into emp2 select * from emp2
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying it in parallel
Help: https://docs.oracle.com/error-help/db/ora-12838/

19c 환경처럼 에러가 발생함

 

 

26ai에서는 APPEND 힌트와 NO_MULTI_APPEND 힌트를 사용한 경우 하나의 트랜잭션 내에서 Direct Path Insert 후 조회 및 Insert 재수행이 불가능함
19c 환경처럼 에러가 발생함

 

 

테스트 데이터 원복

1
2
3
SQL> rollback;
 
Rollback complete.

 

 

7. NOAPPEND와 비교
NO_MULTI_APPEND와 NOAPPEND의 차이를 확인해봄

 

 

먼저 NOAPPEND 힌트만 사용하여 insert 수행

1
2
3
SQL> insert /*+ noappend */ into emp2 select * from emp2;
 
14 rows created.

 

 

COMMIT 하지 않은 상태에서 바로 실행계획 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
SQL> SELECT * FROM DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST -rows -Projection +HINT_REPORT +outline');
 
Plan hash value: 2941272003
 
----------------------------------------------------------------------------------
| Id  | Operation                | Name | Starts | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |      |      1 |      0 |00:00:00.01 |      37 |
|   1 |  LOAD TABLE CONVENTIONAL | EMP2 |      1 |      0 |00:00:00.01 |      37 |
|   2 |   TABLE ACCESS FULL      | EMP2 |      1 |     14 |00:00:00.01 |       7 |
----------------------------------------------------------------------------------
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('23.1.0')
      DB_VERSION('23.1.0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      OUTLINE_LEAF(@"INS$1")
      LOAD_METHOD(@"INS$1" "EMP2"@"INS$1" CONVENTIONAL)
      LOAD_TYPE(@"INS$1" "EMP2"@"INS$1" SERIAL)
      FULL(@"INS$1" "EMP2"@"INS$1")
      FULL(@"SEL$1" "EMP2"@"SEL$1")
      END_OUTLINE_DATA
  */
 
 
32 rows selected.

실행계획에서 LOAD TABLE CONVENTIONAL이 보임
direct path insert가 아닌 conventional insert로 동작했다는 뜻임

 

 

이 경우에는 COMMIT 하지 않고 조회시 잘 조회됨

1
2
3
4
5
SQL> select count(*) from emp2;
 
  COUNT(*)
----------
        28

 

 

다시 INSERT도 당연히 잘됨

1
2
3
SQL> insert into emp2 select * from emp2;
 
28 rows created.

 

 

테스트 데이터 원복

1
2
3
SQL> rollback;
 
Rollback complete.

 

 

결론 :
오라클 26ai에서는 APPEND 힌트를 사용하여 Direct Path Insert를 수행한 후에도
트랜잭션을 종료하지 않고 동일한 테이블을 조회하거나 추가 Direct Path Insert를 수행할 수 있음
APPEND만 사용한 경우와 APPEND + MULTI_APPEND를 명시한 경우 동일하게 동작하는 것을 확인할 수 있음

 

반면 APPEND + NO_MULTI_APPEND 힌트를 사용하면 Direct Path Insert 자체는 그대로 수행되지만
Direct Path Insert 이후 동일 테이블에 접근할 때 기존 19c와 동일하게 ORA-12838 에러가 발생함

 

NO_MULTI_APPEND는 APPEND를 Conventional Insert로 변경하는 힌트가 아니라
26ai에서 해제된 Direct Path Insert의 트랜잭션 제약을 다시 적용하는 용도로 보임
_online_direct_load 히든 파라미터의 힌트 버전? 같은 느낌으로 보면 될것 같음

 

요약 :
NOAPPEND
- APPEND와 반대되는 힌트
- Direct Path Insert를 사용하지 않음
- Conventional Insert로 수행
- 동일 트랜잭션에서 조회 가능

 

NO_MULTI_APPEND
- APPEND 힌트와 함께 사용 가능
- Direct Path Insert는 그대로 사용
- LOAD AS SELECT로 수행
- Direct Path Insert 이후 SELECT 또는 추가 DML 수행시 ORA-12838 발생

 

MULTI_APPEND
- APPEND 힌트와 함께 사용 가능
- Direct Path Insert는 그대로 사용
- LOAD AS SELECT로 수행
- Direct Path Insert 이후 SELECT 또는 추가 DML 수행시 에러 미발생(26ai 기본값)

 

 

참조 : 

오라클 26ai 신기능 Direct Load(Direct Path Insert) 에 대한 제약 해제 ( https://positivemh.tistory.com/1127 )
오라클 26ai 신기능 load_method, load_type 힌트 ( https://positivemh.tistory.com/1128 )
오라클 26ai 신기능 Parallel DML 에 대한 트랜잭션 제한 해제 ( https://positivemh.tistory.com/1176 )
https://oracle-randolf.blogspot.com/2023/08/oracle-23c-free-unrestricted-direct.html
https://tuna.tistory.com/102