Oracle 23c부터 Direct Load 후 커밋을 수행하지 않더라도 동일 세션에서 쿼리 또는 DML 문을 수행할 수 있도록 Direct Load 기능이 개선되었습니다. 참고로 New Features Guide에 Direct Load 후 다른 세션에서 DML 문을 수행할 수 있다는 내용이 있습니다.
Prior to this feature, after a direct load and prior to a commit, queries and additional DMLs were not allowed on the same table for the same session or for other database sessions. This enhancement allows the loading session to query and perform DML on the same table that was loaded. Other sessions are also able to concurrently perform direct loads and DML. Rollback to a savepoint is also supported. This feature removes the restrictions that you may have encountered when loading and querying data. Potentially improving the performance of your applications in areas such as Data Warehousing and complex batch processing.
테스트를 위해 아래와 같이 테이블을 생성하겠습니다.
-- 1
DROP TABLE t1 PURGE;
DROP TABLE t2 PURGE;
CREATE TABLE t1 (c1 NUMBER);
CREATE TABLE t2 (c1) AS SELECT ROWNUM FROM XMLTABLE ('1 to 10000');
Direct Load 후 동일 세션에서 쿼리를 수행하면 23.2 버전은 결과가 반환되지만, 19.3 버전은 ORA-12383 에러가 발생합니다. 하지만 문서의 내용과 달리 23.2 버전도 다른 세션에서 DML 문을 수행하면 enq: TM - contention 이벤트를 대기합니다.
-- 2-1: 23.2
INSERT /*+ APPEND */ INTO t1 SELECT * FROM t2;
10000 행이 생성되었습니다.
SELECT COUNT (*) AS c1 FROM t1;
C1
-----
10000
1개의 행이 선택되었습니다.
-- 2-2: 19.3
INSERT /*+ APPEND */ INTO t1 SELECT * FROM t2;
10000 행이 생성되었습니다.
SELECT COUNT (*) AS c1 FROM t1;
ORA-12838: 병렬로 수정한 후 객체를 읽거나 수정할 수 없습니다
참고로 해당 기능은 _online_direct_load 파라미터와 관련이 있습니다.
NUM NAME VALUE DEFAULT_VALUE DESCRIPTION
---- ------------------- ----- ------------- ------------------
3309 _online_direct_load 1 1 Online Direct Load
VLDB and Partitioning Guide의 Restrictions on Parallel DML 항목에 NO_MULTI_STATEMENT 힌트에 대한 내용이 있습니다.
The restrictions on multiple queries and DML/PDML operations as well as the restriction on multiple direct-path inserts in the same session can be reinstated when needed by including the NO_MULTI_STATEMENT hint in SQL statements.
V$SQL_HINT 뷰에서 MULTI로 시작하는 힌트를 조회하면 MULTI_STATEMENT 힌트 대신 23.1 버전에 추가된 MULTI_APPEND 힌트를 찾을 수 있습니다.
-- 3
SELECT name, inverse, target_level, version
FROM v$sql_hint
WHERE name LIKE 'MULTI%';
NAME INVERSE TARGET_LEVEL VERSION
------------ --------------- ------------ -------
MULTI_APPEND NO_MULTI_APPEND 1 23.1.0
1개의 행이 선택되었습니다.
INSERT 문에 MULTI_APPEND 힌트를 사용하면 INSERT 문이 Conventional Load로 동작하는 것을 확인할 수 있습니다. 아마도 23.2 버전까지 기능이 구현되지 않은 것으로 판단됩니다. 향후 추가 테스트가 필요할 것으로 보입니다.
-- 4
INSERT /*+ MULTI_APPEND */ INTO t1 SELECT * FROM t2;
--------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)|
--------------------------------------------------------------
| 0 | INSERT STATEMENT | | 10000 | 5 (0)|
| 1 | LOAD TABLE CONVENTIONAL | T1 | | |
| 2 | TABLE ACCESS FULL | T2 | 10000 | 5 (0)|
--------------------------------------------------------------
관련 링크