DML ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น๋ ์์
์ธ๋ฑ์ค์ DML ์ฑ๋ฅ
- ํ
์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ์
๋ ฅํ๋ฉด, ์ธ๋ฑ์ค์๋ ์
๋ ฅํด์ผ ํจ
- ํ ์ด๋ธ์ Freelist๋ฅผ ํตํด ์ ๋ ฅํ ๋ธ๋ก์ ํ ๋น
- ์ธ๋ฑ์ค๋ ์ ๋ ฌ๋ ์๋ฃ๊ตฌ์กฐ์ด๋ฏ๋ก, ์์ง์ ํ์์ ํตํด ์ ๋ ฅํ ๋ธ๋ก์ ์ฐพ์์ผ ํจ
- ์ธ๋ฑ์ค์ ์ ๋ ฅํ๋ ๊ณผ์ ์ด ๋ ๋ณต์กํ๋ฏ๋ก, DML ์ฑ๋ฅ์ ๋ฏธ์น๋ ์ํฅ๋ ํผ
- DELETE๋ก ํ ์ด๋ธ์์ ๋ ์ฝ๋ ํ๋๋ฅผ ์ญ์ ํ๋ฉด, ์ธ๋ฑ์ค ๋ ์ฝ๋๋ฅผ ๋ชจ๋ ์ฐพ์์ ์ญ์ ํด์ผ ํจ

- UPDATE๋ ๋ณ๊ฒฝ๋ ์ปฌ๋ผ์ ์ฐธ์กฐํ๋ ์ธ๋ฑ์ค๋ง ์ฐพ์์ ๋ณ๊ฒฝ
- ํ
์ด๋ธ์์ ํ ๊ฑด ๋ณ๊ฒฝํ ๋๋ง๋ค ์ธ๋ฑ์ค์๋ ๋ ๊ฐ ์คํผ๋ ์ด์
์ด ๋ฐ์
- ์ธ๋ฑ์ค๋ ์ ๋ ฌ๋ ์๋ฃ๊ตฌ์กฐ์ด๊ธฐ ๋๋ฌธ
- 'A'๋ฅผ 'K'๋ก ๋ณ๊ฒฝํ๋ฉด ์ ์ฅ ์์น๋ ๋ฌ๋ผ์ง๋ฏ๋ก ์ญ์ ํ ์ฝ์ ํ๋ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌ
- ํ
์ด๋ธ์์ ํ ๊ฑด ๋ณ๊ฒฝํ ๋๋ง๋ค ์ธ๋ฑ์ค์๋ ๋ ๊ฐ ์คํผ๋ ์ด์
์ด ๋ฐ์

- ์ธ๋ฑ์ค ๊ฐ์๊ฐ DML ์ฑ๋ฅ์ ๋ฏธ์น๋ ์ํฅ์ด ํฐ ๋งํผ, ์ค๊ณ์ ์ฌํ์ ๊ธฐ์ธ์ฌ์ผ ํจ
- ํต์ฌ ํธ๋์ญ์ ํ ์ด๋ธ์์ ์ธ๋ฑ์ค๋ฅผ ํ๋๋ผ๋ ์ค์ด๋ฉด TPS๋ ํฅ์๋จ
SQL> create table source
2 as
3 select b.no, a.*
4 from (select * from emp where rownum <= 10) a
5 ,(select rownum as no from dual connect by level <= 100000) b;
SQL> create table target
2 as
3 select * from source where 1 = 2;
SQL> alter table target add
2 constraint target_pk primary key(no, empno);
SQL> set timing on;
SQL> insert into target
2 select * from source;
1000000 ๊ฐ์ ํ์ด ๋ง๋ค์ด์ก์ต๋๋ค.
๊ฒฝ ๊ณผ: 00:00:04.95
SQL> truncate table target;
SQL> create index target_x1 on target(ename);
SQL> create index target_x2 on target(deptno, mgr);
SQL> insert into target
2 select * from source;
1000000 ๊ฐ์ ํ์ด ๋ง๋ค์ด์ก์ต๋๋ค.
๊ฒฝ ๊ณผ: 00:00:38.98
๋ฌด๊ฒฐ์ฑ ์ ์ฝ๊ณผ DML ์ฑ๋ฅ
- ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๊ท์น
- ๊ฐ์ฒด ๋ฌด๊ฒฐ์ฑ(Entity Integrity)
- ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ(Referential Integrity)
- ๋๋ฉ์ธ ๋ฌด๊ฒฐ์ฑ(Domain Integrity)
- ์ฌ์ฉ์ ์ ์ ๋ฌด๊ฒฐ์ฑ(๋๋ ์ ๋ฌด ์ ์ฝ ์กฐ๊ฑด)
- ์ด๋ค ๊ท์น์ ์ ํ๋ฆฌ์ผ์ด์ ๋ฟ๋ง ์๋๋ผ DBMS์์ PK, FK, Check, Not Null ๊ฐ์ Constraint๋ก ๋ ์๋ฒฝํ๊ฒ ์ง์ผ๋ผ ์ ์์
- PK, FK๋ Check, Not Null ๋ณด๋ค ์ฑ๋ฅ์ ๋ ํฐ ์ํฅ
- ์ค์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํด ๋ด์ผ ํ๊ธฐ ๋๋ฌธ
SQL> drop index target_x1;
SQL> drop index target_x2;
SQL> alter table target drop primary key;
SQL> truncate table target;
SQL> insert into target
2 select * from source;
1000000 ๊ฐ์ ํ์ด ๋ง๋ค์ด์ก์ต๋๋ค.
๊ฒฝ ๊ณผ: 00:00:01.32
| PK ์ ์ฝ/์ธ๋ฑ์ค | ์ผ๋ฐ ์ธ๋ฑ์ค(2๊ฐ) | ์์์๊ฐ |
|---|---|---|
| O | O | 38.98์ด |
| O | X | 4.95์ด |
| X | X | 1.32์ด |
์กฐ๊ฑด์ ๊ณผ DML ์ฑ๋ฅ
- SELECT๋ฌธ๊ณผ ํฌ๊ฒ ๋ค๋ฅด์ง ์์
SQL> set autotrace traceonly exp
SQL> update emp set sal = sal * 1.1 where deptno = 40;
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 7 | 2 (0)| 00:00:01 |
| 1 | UPDATE | EMP | | | | |
| 2 | INDEX RANGE SCAN| EMP_X01 | 1 | 7 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
SQL> delete from emp where deptno = 40;
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 |
| 1 | DELETE | EMP | | | | |
| 2 | INDEX RANGE SCAN| EMP_X01 | 1 | 13 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
์๋ธ์ฟผ๋ฆฌ์ DML ์ฑ๋ฅ
- SELECT๋ฌธ๊ณผ ํฌ๊ฒ ๋ค๋ฅด์ง ์์ผ๋ฏ๋ก ์กฐ์ธ ํ๋ ์๋ฆฌ ์ ์ฉ ๊ฐ๋ฅ
SQL> update emp e set sal = sal * 1.1
2 where exists
3 (select 'x' from dept where deptno = e.deptno and loc = 'CHICAGO');
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 5 | 90 | 5 (20)|
| 1 | UPDATE | EMP | | | |
| 2 | NESTED LOOPS | | 5 | 90 | 5 (20)|
| 3 | SORT UNIQUE | | 1 | 11 | 2 (0)|
| 4 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 11 | 2 (0)|
| 5 | INDEX RANGE SCAN | DEPT_X01 | 1 | | 1 (0)|
| 6 | INDEX RANGE SCAN | EMP_X01 | 5 | 35 | 1 (0)|
---------------------------------------------------------------------------------
SQL> delete from emp e
2 where exists
3 (select 'x' from dept where deptno = e.deptno and loc = 'CHICAGO');
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 5 | 120 | 4 (25)|
| 1 | DELETE | EMP | | | |
| 2 | HASH JOIN SEMI | | 5 | 120 | 4 (25)|
| 3 | INDEX FULL SCAN | EMP_X01 | 14 | 182 | 1 (0)|
| 4 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 11 | 2 (0)|
| 5 | INDEX RANGE SCAN | DEPT_X01 | 1 | | 1 (0)|
---------------------------------------------------------------------------------
SQL> insert into emp
2 select e.*
3 from emp_t e
4 where exists
5 (select 'x' from dept where deptno = e.deptno and loc = 'CHICAGO');
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 5 | 490 | 6 (17)|
| 1 | LOAD TABLE CONVENTIONAL | EMP | | | |
| 2 | HASH JOIN SEMI | | 5 | 490 | 6 (17)|
| 3 | TABLE ACCESS FULL | EMP_T | 14 | 1218 | 3 (0)|
| 4 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 11 | 2 (0)|
| 5 | INDEX RANGE SCAN | DEPT_X01 | 1 | | 1 (0)|
---------------------------------------------------------------------------------
Redo ๋ก๊น ๊ณผ DML ์ฑ๋ฅ
- ์ค๋ผํด์ ๋ฐ์ดํฐํ์ผ๊ณผ ์ปจํธ๋กค ํ์ผ์ ๊ฐํด์ง๋ ๋ชจ๋ ๋ณ๊ฒฝ์ฌํญ์ Redo ๋ก๊ทธ์ ๊ธฐ๋ก
- ํธ๋์ญ์ ๋ฐ์ดํฐ๊ฐ ์ ์ค๋์ ๋, ํธ๋์ญ์ ์ ์ฌํํจ์ผ๋ก์จ ์ ์ค ์ด์ ์ํ๋ก ๋ณต๊ตฌํ๋ ๋ฐ ์ด์ฉ
- DML์ ์ํํ ๋๋ง๋ค Redo ๋ก๊ทธ๋ฅผ ์์ฑํด์ผ ํ๋ฏ๋ก Redo ๋ก๊น ์ DML ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์นจ
- Redo ๋ก๊ทธ์ ์ฉ๋
- Database Recovery(๋๋ Media Recovery)
- ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋์คํฌ๊ฐ ๊นจ์ง๋ ๋ฑ Media Fail ๋ฐ์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ณต๊ตฌํ๊ธฐ ์ํด ์ฌ์ฉ
- ์จ๋ผ์ธ Redo ๋ก๊ทธ๋ฅผ ๋ฐฑ์ ํด ๋ Archived Redo ๋ก๊ทธ ์ด์ฉ
- Cache Recovery (Instance Recovery ์ roll forward ๋จ๊ณ)
- I/O ์ฑ๋ฅ์ ๋์ด๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ฒํผ์บ์๋ ํ๋ฐ์ฑ
- ์บ์์ ์ ์ฅ๋ ๋ณ๊ฒฝ์ฌํญ์ด ๋์คํฌ ์์ ๋ฐ์ดํฐ ๋ธ๋ก์ ์์ง ๊ธฐ๋ก๋์ง ์์ ์ํ์์ ์ธ์คํด์ค๊ฐ ๋น์ ์์ ์ผ๋ก ์ข ๋ฃ๋๋ฉด, ์์ ๋ด์ฉ์ด ๋ชจ๋ ์ ์ค๋จ
- ํธ๋์ญ์ ๋ฐ์ดํฐ ์ ์ค์ ๋๋นํ๊ธฐ ์ํด Redo ๋ก๊ทธ ์ฌ์ฉ
- I/O ์ฑ๋ฅ์ ๋์ด๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ฒํผ์บ์๋ ํ๋ฐ์ฑ
- Fast Commit
- ๋ณ๊ฒฝ๋ ๋ฉ๋ชจ๋ฆฌ ๋ฒํผ๋ธ๋ก์ ๋์คํฌ ์์ ๋ฐ์ดํฐ ๋ธ๋ก์ ๋ฐ์ํ๋ ์์ ์ ๋๋ค ์์ธ์ค ๋ฐฉ์์ผ๋ก ๋งค์ฐ ๋๋ฆผ
- ๋ก๊ทธ๋ Append ๋ฐฉ์์ผ๋ก ๊ธฐ๋กํ๋ฏ๋ก ์๋์ ์ผ๋ก ๋น ๋ฆ
- ํธ๋์ญ์
์ ์ํ ๋ณ๊ฒฝ์ฌํญ์ ์ฐ์ Append ๋ฐฉ์์ผ๋ก ๋ก๊ทธ ํ์ผ์ ๋น ๋ฅด๊ฒ ๊ธฐ๋ก
- ๋ณ๊ฒฝ๋ ๋ฉ๋ชจ๋ฆฌ ๋ฒํผ๋ธ๋ก๊ณผ ๋ฐ์ดํฐํ์ผ ๋ธ๋ก ๊ฐ์ ๋๊ธฐํ๋ DBWR, Checkpoint ๋ฑ์ ์ด์ฉํด Batch ๋ฐฉ์์ผ๋ก ์ผ๊ด ์ํ
- Fast Commit์ ์ฌ์ฉ์์ ๊ฐฑ์ ๋ด์ฉ์ด ๋ฉ๋ชจ๋ฆฌ์์ ๋ฒํผ๋ธ๋ก์๋ง ๊ธฐ๋ก๋ ์ฑ ์์ง ๋์คํฌ์ ๊ธฐ๋ก๋์ง ์์์ง๋ง Redo ๋ก๊ทธ๋ฅผ ๋ฏฟ๊ณ ๋น ๋ฅด๊ฒ ์ปค๋ฐ์ ์๋ฃํ๋ค๋ ์๋ฏธ
- ์ปค๋ฐ ์ ๋ณด๊น์ง Redo ๋ก๊ทธ ํ์ผ์ ์์ ํ๊ฒ ๊ธฐ๋กํ๋ค๋ฉด, ์ธ์คํด์ค Crash๊ฐ ๋ฐ์ํด๋ ์ธ์ ๋ ๋ณต๊ตฌํ ์ ์์
- Database Recovery(๋๋ Media Recovery)
Undo๋ก๊น ๊ณผ DML ์ฑ๋ฅ
- Redo๋ ํธ๋์ญ์ ์ ์ฌํํจ์ผ๋ก์จ ๊ณผ๊ฑฐ๋ฅผ ํ์ฌ ์ํ๋ก ๋๋๋ฆฌ๋ ๋ฐ ์ฌ์ฉ
- Undo๋ ํธ๋์ญ์ ์ ๋กค๋ฐฑํจ์ผ๋ก์จ ํ์ฌ๋ฅผ ๊ณผ๊ฑฐ ์ํ๋ก ๋๋๋ฆฌ๋ ๋ฐ ์ฌ์ฉ

- Redo๋ ํธ๋์ญ์ ์ ์ฌํํ๋ ๋ฐ ํ์ํ ์ ๋ณด๋ฅผ ๋ก๊น
- Undo๋ ๋ณ๊ฒฝ๋ ๋ธ๋ก์ ์ด์ ์ํ๋ก ๋๋๋ฆฌ๋ ๋ฐ ํ์ํ ์ ๋ณด๋ฅผ ๋ก๊น
- DML ์ํํ ๋๋งค๋ค Undo๋ฅผ ์์ฑํด์ผ ํ๋ฏ๋ก Undo ๋ก๊น ์ DML ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์นจ
Undo์ ์ฉ๋์ MVCC ๋ชจ๋ธ
- ์ค๋ผํด์ ๋ฐ์ดํฐ๋ฅผ ์
๋ ฅ/์์ /์ญ์ ํ ๋๋ง๋ค Undo ์ธ๊ทธ๋จผํธ์ ๊ธฐ๋ก์ ๋จ๊น
- Undo ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋กํ ๊ณต๊ฐ์ ํด๋น ํธ๋์ญ์ ์ด ์ปค๋ฐํ๋ ์๊ฐ, ๋ค๋ฅธ ํธ๋์ญ์ ์ด ์ฌ์ฌ์ฉํ ์ ์๋ ์ํ๋ก ๋ฐ๋
- ๊ฐ์ฅ ์ค๋ ์ ์ ์ปค๋ฐํ Undo ๊ณต๊ฐ๋ถํฐ ์ฌ์ฌ์ฉํ๋ฏ๋ก, ์ธ์ ๊ฐ ๋ค๋ฅธ ํธ๋์ญ์ ๋ฐ์ดํฐ๋ก ๋ฎ์ฌ์ฐ์
- Undo์ ๊ธฐ๋กํ ๋ฐ์ดํฐ์ ์ฉ๋
- Transaction Rollback
- ํธ๋์ญ์ ์ ์ํ ๋ณ๊ฒฝ์ฌํญ์ ์ต์ข ์ปค๋ฐํ์ง ์๊ณ ๋กค๋ฐฑํ ๋ ์ด์ฉ
- Transaction Recovery (Instacne Recovery์ rollback ๋จ๊ณ)
- Instance Crash ๋ฐ์ ํ Redo๋ฅผ ์ด์ฉํด roll forward ๋จ๊ณ๊ฐ ์๋ฃ๋๋ฉด ์ต์ข ์ปค๋ฐ๋์ง ์์ ๋ณ๊ฒฝ์ฌํญ๊น์ง ๋ชจ๋ ๋ณต๊ตฌ
- ์์คํ ์ด ์ ง๋ค์ด๋ ์์ ์ ์์ง ์ปค๋ฐ๋์ง ์์๋ ํธ๋์ญ์ ์ ๋ชจ๋ ๋กค๋ฐฑํด์ผ ํ๋๋ฐ, ์ด๋ Undo ๋ฐ์ดํฐ ์ด์ฉ
- Read Consistency
- ์ฝ๊ธฐ ์ผ๊ด์ฑ์ ์ํด ์ฌ์ฉ
- ์ฝ๊ธฐ ์ผ๊ด์ฑ์ ์ํด Consistent ๋ชจ๋๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ์ค๋ผํด์์ ๋์ ํธ๋์ญ์ ์ด ๋ง์์ง์๋ก ๋ธ๋ก I/O๊ฐ ์ฆ๊ฐํ๋ฉด์ ์ฑ๋ฅ ์ ํ๋ก ์ด์ด์ง
- Transaction Rollback
- MVCC(Multi-Version Concurrency Control) ๋ชจ๋ธ
MVCC ๋ชจ๋ธ์ ์ฌ์ฉํ๋ ์ค๋ผํด์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๋ชจ๋
Current ๋ชจ๋
- ๋์คํฌ์์ ์บ์๋ก ์ ์ฌ๋ ์๋ณธ(Current) ๋ธ๋ก์ ํ์ฌ ์ํ ๊ทธ๋๋ก ์ฝ์
Consistent ๋ชจ๋
- ์ฟผ๋ฆฌ๊ฐ ์์๋ ์ดํ ๋ค๋ฅธ ํธ๋์ญ์ ์ ์ํด ๋ณ๊ฒฝ๋ ๋ธ๋ก์ ๋ง๋๋ฉด ์๋ณต ๋ธ๋ก์ผ๋ก๋ถํฐ ๋ณต์ฌ๋ณธ(CR Copy) ๋ธ๋ก ๋ง๋ฆ
- ๋ณต์ฌ๋ณธ์ Undo ๋ฐ์ดํฐ๋ฅผ ์ ์ฉํด ์ฟผ๋ฆฌ๊ฐ ์์๋ ์์ ์ผ๋ก ๋๋๋ ค์ ์ฝ์

์๋ณธ ๋ธ๋ก ํ๋์ ์ฌ๋ฌ ๋ณต์ฌ๋ณธ์ด ์บ์์ ์กด์ฌํ ์ ์์
SCN(System Commit Number)
- ์ค๋ผํด์ ์์คํ
์์ ๋ง์ง๋ง ์ปค๋ฐ์ด ๋ฐ์ํ ์์ ์ ๋ณด๋ฅผ SCN์ด๋ผ๋ Global ๋ณ์๊ฐ์ผ๋ก ๊ด๋ฆฌ
- ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ ํธ๋์ญ์ ์ด ์ปค๋ฐํ ๋๋ง๋ค 1์ฉ ์ฆ๊ฐ
- ์ค๋ผํด ๋ฐฑ๊ทธ๋ผ์ด๋ ํ๋ก์ธ์์ ์ํด์๋ ์กฐ๊ธ์ฉ ์ฆ๊ฐ
- ์ค๋ผํด์ ๊ฐ ๋ธ๋ก์ด ๋ง์ง๋ง์ผ๋ก ๋ณ๊ฒฝ๋ ์์ ์ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ชจ๋ ๋ธ๋ก ํค๋์ SCN ๊ธฐ๋ก
- ๋ธ๋ก SCN
- ๋ชจ๋ ์ฟผ๋ฆฌ๋ Global ๋ณ์์ธ SCN ๊ฐ์ ๋จผ์ ํ์ธํ๊ณ ์ ์ฝ๊ธฐ ์์
์์
- ์ฟผ๋ฆฌ SCN
- ์ค๋ผํด์ ์์คํ
์์ ๋ง์ง๋ง ์ปค๋ฐ์ด ๋ฐ์ํ ์์ ์ ๋ณด๋ฅผ SCN์ด๋ผ๋ Global ๋ณ์๊ฐ์ผ๋ก ๊ด๋ฆฌ
Consistent ๋ชจ๋๋ ์ฟผ๋ฆฌ SCN๊ณผ ๋ธ๋ก SCN์ ๋น๊ตํจ์ผ๋ก์จ ์ฟผ๋ฆฌ ์ํ ๋์ค์ ๋ธ๋ก์ด ๋ณ๊ฒฝ๋๋์ง๋ฅผ ํ์ธํ๋ฉด์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
- ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ค ๋ธ๋ก SCN์ด ์ฟผ๋ฆฌ SCN๋ณด๋ค ํฐ ๋ธ๋ก์ ๋ง๋๋ฉด ๋ณต์ฌ๋ณธ ๋ธ๋ก ์์ฑ
- Undo ๋ฐ์ดํฐ๋ฅผ ์ ์ฉํด ์ฟผ๋ฆฌ๊ฐ ์์๋ ์์ ์ผ๋ก ๋๋๋ ค์ ์ฝ์
SELECT ๋ฌธ์ ๋ช๋ช ์์ธ๋ฅผ ์ ์ธํ๊ณ ๋ ํญ์ Consistent ๋ชจ๋๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ์
DML์ Consistent ๋ชจ๋๋ก ๋์ ๋ ์ฝ๋๋ฅผ ์ฐพ๊ณ , Current ๋ชจ๋๋ก ์ถ๊ฐ/๋ณ๊ฒฝ/์ญ์
- Consistent ๋ชจ๋๋ก DML ๋ฌธ์ด ์์๋ ์์ ์ ์กด์ฌํ๋ ๋ฐ์ดํฐ ๋ธ๋ก ์ฐพ์
- ์ฝ๊ธฐ ์ผ๊ด์ฑ์ ์ํจ
- Current ๋ชจ๋๋ก ์๋ณธ ๋ธ๋ก ๊ฐฑ์
- Consistent ๋ชจ๋๋ก DML ๋ฌธ์ด ์์๋ ์์ ์ ์กด์ฌํ๋ ๋ฐ์ดํฐ ๋ธ๋ก ์ฐพ์
Lock๊ณผ DML ์ฑ๋ฅ
- Lock์ ํ์ ์ด์์ผ๋ก ์์ฃผ, ๊ธธ๊ฒ ์ฌ์ฉํ๊ฑฐ๋ ๋ ๋ฒจ์ ๋์ผ์๋ก DML ์ฑ๋ฅ์ด ๋๋ ค์ง
- Lock์ ๋๋ฌด ์ ๊ฒ, ์งง๊ฒ ์ฌ์ฉํ๊ฑฐ๋ ํ์ํ ๋ ๋ฒจ ์ดํ๋ก ๋ฎ์ถ๋ฉด ๋ฐ์ดํฐ ํ์ง์ด ๋๋น ์ง
์ปค๋ฐ๊ณผ DML ์ฑ๋ฅ
- ์ปค๋ฐ์ DML๊ณผ ๋ณ๊ฐ๋ก ์คํํ์ง๋ง, DML์ ๋๋ด๋ ค๋ฉด ์ปค๋ฐ๊น์ง ์๋ฃํด์ผ ํจ
- DML์ด Lock์ ์ํด Blocking๋ ๊ฒฝ์ฐ, DML์ด ์๋ฃํ ์ ์๊ฒ Lock์ ํธ๋ ์ด์ ๊ฐ ์ปค๋ฐ์ด๋ฏ๋ก, ์ปค๋ฐ์ DML ์ฑ๋ฅ๊ณผ ์ง๊ฒฐ
- ๋ชจ๋ DBMS๊ฐ Fast Commit์ ๊ตฌํํ๊ณ ์์
- ๊ฐฑ์ ํ ๋ฐ์ดํฐ๊ฐ ์๋ฌด๋ฆฌ ๋ง์๋ ์ปค๋ฐ๋งํผ์ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌ
- ์ปค๋ฐ ๋ด๋ถ ๋ฉ์ปค๋์ฆ
DB ๋ฒํผ์บ์
- DB์ ์ ์ํ ์ฌ์ฉ์๋ฅผ ๋์ ํด ๋ชจ๋ ์ผ์ ์ฒ๋ฆฌํ๋ ์๋ฒ ํ๋ก์ธ์ค๋ ๋ฒํผ์บ์๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์
- ๋ฒํผ์บ์์ ๋ณ๊ฒฝ๋ ๋ธ๋ก(Dirty Block)์ ๋ชจ์ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ฐ์ดํฐํ์ผ์ ์ผ๊ด ๊ธฐ๋กํ๋ ์์
์ DBWR(Database Writer) ํ๋ก์ธ์ค๊ฐ ๋ด๋น
- ๊ฑด๊ฑด์ด ์ฒ๋ฆฌํ์ง ์๊ณ ๋ชจ์๋ค๊ฐ ํ ๋ฒ์ ์ผ๊ด(Batch) ์ฒ๋ฆฌ
Redo ๋ก๊ทธ๋ฒํผ
- ๋ฒํผ์บ์๋ ํ๋ฐ์ฑ์ด๋ฏ๋ก DBWR ํ๋ก์ธ์ค๊ฐ Dirty Block์ ๋ฐ์ดํฐํ์ผ์ ๋ฐ์ํ ๋๊น์ง ๋ถ์ํ ์ํ
- ๋ฒํผ์บ์์ ๊ฐํ ๋ณ๊ฒฝ์ฌํญ์ Redo ๋ก๊ทธ์๋ ๊ธฐ๋ก
- ๋ฒํผ์บ์ ๋ฐ์ดํฐ๊ฐ ์ ์ค๋๋๋ผ๋ Redo ๋ก๊ทธ๋ฅผ ์ด์ฉํด ๋ณต๊ตฌ ๊ฐ๋ฅ
- Redo ๋ก๊ทธ๋ ํ์ผ
- Append ๋ฐฉ์์ผ๋ก ๊ธฐ๋กํ๋๋ผ๋ ๋์คํฌ I/O๋ ๋๋ฆผ
- Redo ๋ก๊น
์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ก๊ทธ๋ฒํผ ์ด์ฉ
- Redo ๋ก๊ทธ ํ์ผ์ ๊ธฐ๋กํ๊ธฐ ์ ์ ๋จผ์ ๋ก๊ทธ๋ฒํผ์ ๊ธฐ๋ก
- ๊ธฐ๋กํ ๋ด์ฉ์ ๋์ค์ LGWR(Log Writer) ํ๋ก์ธ์ค๊ฐ Redo ๋ก๊ทธ ํ์ผ์ ์ผ๊ด(Batch) ๊ธฐ๋ก
ํธ๋์ญ์ ๋ฐ์ดํฐ ์ ์ฅ ๊ณผ์
- DML๋ฌธ์ ์คํํ๋ฉด Redo ๋ก๊ทธ๋ฒํผ์ ๋ณ๊ฒฝ์ฌํญ ๊ธฐ๋ก
- ๋ฒํผ๋ธ๋ก์์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝ(๋ ์ฝ๋ ์ถ๊ฐ/์์ /์ญ์ )
- ๋ฒํผ์บ์์์ ๋ธ๋ก์ ์ฐพ์ง ๋ชปํ๋ฉด, ๋ฐ์ดํฐํ์ผ์์ ์ฝ๋ ์์ ๋ถํฐ
- ์ปค๋ฐ
- LGWR ํ๋ก์ธ์ค๊ฐ Redo ๋ก๊ทธ๋ฒํผ ๋ด์ฉ์ ๋ก๊ทธํ์ผ์ ์ผ๊ด ์ ์ฅ
- DBWR ํ๋ก์ธ์ค๊ฐ ๋ณ๊ฒฝ๋ ๋ฒํผ๋ธ๋ก๋ค์ ๋ฐ์ดํฐํ์ผ์ ์ผ๊ด ์ ์ฅ

- ์ค๋ผํด์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ์ ์ ํญ์ ๋ก๊ทธ๋ถํฐ ๊ธฐ๋ก
- Write Ahead Logging
- ๋ฉ๋ชจ๋ฆฌ ๋ฒํผ์บ์๊ฐ ํ๋ฐ์ฑ์ด์ด์ Redo ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋๋ฐ, Redo ๋ก๊ทธ๋ง์ ํ๋ฐ์ฑ ๋ก๊ทธ๋ฒํผ์ ๊ธฐ๋กํ๋ค๋ฉด ํธ๋์ญ์
๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ฒ ์งํฌ ์ ์์๊น
- DBWR/LGWR ํ๋ก์ธ์ค๋ ์ฃผ๊ธฐ์ ์ผ๋ก ๊นจ์ด๋ ๊ฐ๊ฐ Dirty Block๊ณผ Redo ๋ก๊ทธ๋ฒํผ๋ฅผ ํ์ผ์ ๊ธฐ๋ก
- LGWR ํ๋ก์ธ์ค๋ ์๋ฒ ํ๋ก์ธ์ค๊ฐ ์ปค๋ฐ์ ๋ฐํํ๋ค๊ณ ์ ํธ๋ฅผ ๋ณด๋ผ๋๋ ๊นจ์ด๋์ ํ๋์ ์์
- ์ ์ด๋ ์ปค๋ฐ์์ ์๋ Redo ๋ก๊ทธ๋ฒํผ ๋ด์ฉ์ ๋ก๊ทธํ์ผ์ ๊ธฐ๋ก
- Log Force at Commit
- ์๋ฒ ํ๋ก์ธ์ค๊ฐ ๋ณ๊ฒฝํ ๋ฒํผ๋ธ๋ก๋ค์ ๋์คํฌ์ ๊ธฐ๋กํ์ง ์์๋๋ผ๋ ์ปค๋ฐ ์์ ์ Redo ๋ก๊ทธ๋ฅผ ๋์คํฌ์ ์์ ํ๊ฒ ๊ธฐ๋กํ๋ค๋ฉด ํธ๋์ญ์ ์ ์์์ฑ ๋ณด์ฅ
์ปค๋ฐ = ์ ์ฅ๋ฒํผ
- ์ปค๋ฐ์ ์๋ฒ ํ๋ก์ธ์ค๊ฐ ๊ทธ๋๊น์ง ํ๋ ์์
์ ๋์คํฌ์ ๊ธฐ๋กํ๋ผ๋ ๋ช
๋ น์ด
- ์ ์ฅ์ ์๋ฃํ ๋๊น์ง ์๋ฒ ํ๋ก์ธ์ค๋ ๋ค์ ์์ ์งํ ๋ถ๊ฐ
- Redo ๋ก๊ทธ๋ฒํผ์ ๊ธฐ๋ก๋ ๋ด์ฉ์ ๋์คํฌ์ ๊ธฐ๋กํ๋๋ก LGWR ํ๋ก์ธ์ค์ ์ ํธ๋ฅผ ๋ณด๋ธ ํ ์์ ์ ์๋ฃํ๋ค๋ ์ ํธ๋ฅผ ๋ฐ์์ผ ๋ค์ ์์ ์งํ ๊ฐ๋ฅ(Sync)
- LGWR ํ๋ก์ธ์ค๊ฐ Redo๋ก๊ทธ๋ฅผ ๊ธฐ๋กํ๋ ์์ ์ ๋์คํฌ I/O์์ ์ผ๋ก, ์ปค๋ฐ์ ์๊ฐ๋ณด๋ค ๋๋ฆผ
- ํธ๋์ญ์
์ ํ์ ์ด์์ผ๋ก ๊ธธ๊ฒ ์ ์ํด ์ค๋ซ๋์ ์ปค๋ฐํ์ง ์๋ ๊ฒ์ ์ข์ง ์์
- ์ค๋ซ๋์ ์ปค๋ฐํ์ง ์์ ์ฑ ๋ฐ์ดํฐ๋ฅผ ๊ณ์ ๊ฐฑ์ ํ๋ค๋ฉด Undo ๊ณต๊ฐ์ด ๋ถ์กฑํด์ ธ ์์คํ ์ฅ์ ์ํฉ ์ ๋ฐ
- ๋ฐ๋๋ก ๋๋ฌด ์์ฃผ ์ปค๋ฐํ๋ ๊ฒ๋ ์ข์ง ์์
- ๋ฃจํ๋ฅผ ๋๋ฉด์ ๊ฑด๊ฑด์ด ์ปค๋ฐํ๋ค๋ฉด ํ๋ก๊ทธ๋จ ์์ฒด ์ฑ๋ฅ์ด ๋งค์ฐ ๋๋ ค์ง
- ์ปค๋ฐ์ ์๋ฒ ํ๋ก์ธ์ค๊ฐ ๊ทธ๋๊น์ง ํ๋ ์์
์ ๋์คํฌ์ ๊ธฐ๋กํ๋ผ๋ ๋ช
๋ น์ด
๋ฐ์ดํฐ๋ฒ ์ด์ค Call๊ณผ ์ฑ๋ฅ
๋ฐ์ดํฐ๋ฒ ์ด์ค Call
select cust_nm, birthday from customer where cust_id = :cust_id
call count cpu elapsed disk query current rows
------- ------- -------- --------- --------- --------- --------- ---------
Parse 1 0.00 0.00 0 0 0 0
Execute 5000 0.18 0.14 0 0 0 0
Fetch 5000 0.21 0.25 0 20000 0 50000
------- ------- -------- --------- --------- --------- --------- ---------
total 10001 0.39 0.40 0 20000 0 50000
Misses in library cache during parse: 1
- Parse Call
- SQL ํ์ฑ๊ณผ ์ต์ ํ ์ํ
- SQL๊ณผ ์คํ๊ณํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์บ์์์ ์ฐพ์ผ๋ฉด, ์ต์ ํ ๋จ๊ณ ์๋ต ๊ฐ๋ฅ
- Execute Call
- SQL์ ์คํ
- DML์ ์ด ๋จ๊ณ์์ ๋ชจ๋ ๊ฒ ๋๋์ง๋ง, SELECT๋ฌธ์ Fetch ๋จ๊ณ ๊ฑฐ์นจ
- Fetch Call
- ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด ์ฌ์ฉ์์๊ฒ ๊ฒฐ๊ณผ์งํฉ์ ์ ์ก
- ์ ์กํ ๋ฐ์ดํฐ๊ฐ ๋ง์ ๋๋ Fetch Call์ด ์ฌ๋ฌ ๋ฒ ๋ฐ์

- User Call
- ๋คํธ์ํฌ๋ฅผ ๊ฒฝ์ ํด DBMS ์ธ๋ถ๋ก๋ถํฐ ์ธ์ ๋๋ Call
- Recursive Call
- DBMS ๋ด๋ถ์์ ๋ฐ์ํ๋ Call
- ๋ฐ์ดํฐ ๋์ ๋๋ฆฌ ์กฐํ, PL/SQL๋ก ์์ฑํ ์ฌ์ฉ์ ์ ์ ํจ์/ํ๋ก์์ /ํธ๋ฆฌ๊ฑฐ์ ๋ด์ฅ๋ SQL ์คํ ๋ฑ
- User Call์ด๋ Recursive Call ์ด๋ SQL์ ์คํํ ๋๋ง๋ค Parse, Execute, Fetch Call ๋จ๊ณ ๊ฑฐ์นจ
- ํนํ ๋คํธ์ํฌ๋ฅผ ๊ฒฝ์ ํ๋ User Call์ด ์ฑ๋ฅ์ ๋ฏธ์น๋ ์ํฅ์ด ๋งค์ฐ ํผ
์ ์ฐจ์ ๋ฃจํ ์ฒ๋ฆฌ
SQL> create table source
2 as
3 select b.no, a.*
4 from (select * from emp where rownum <= 10) a
5 ,(select rownum as no from dual connect by level <= 100000) b;
SQL> create table target
2 as
3 select * from source where 1 = 2;
-- SOURCE ํ
์ด๋ธ์ ๋ ์ฝ๋ 1M๊ฐ๊ฐ ์
๋ ฅ๋ผ ์์ ๋
SQL> set timing on;
SQL> begin
2 for s in (select * from source)
3 loop
4 insert into target values ( s.no, s.empno, s.ename, s.job, s.mgr
5 , s.hiredate, s.sal, s.comm, s.deptno );
6 end loop;
7
8 commit;
9 end;
10 /
๊ฒฝ ๊ณผ: 00:00:29.31
- ๋ฃจํ๋ฅผ ๋๋ฉฐ ๊ฑด๊ฑด์ด Call์ ํ์ง๋ง, Recursive Call์ด๋ฏ๋ก 29์ด ๋ง์ ์ํ
-- ๋ฃจํ ์ฒ๋ฆฌ๋ฅผ ๋ชจ๋ ์๋ฃํ๊ณ ์ปค๋ฐํ์ง ์๊ณ , ๋ฃจํ ๋ด๋ถ์์ ์ปค๋ฐ
SQL> begin
2 for s in (select * from source)
3 loop
4
5 insert into target values ( s.no, s.empno, s.ename, s.job, s.mgr
6 , s.hiredate, s.sal, s.comm, s.deptno );
7
8 commit;
9
10 end loop;
11
12 end;
13 /
๊ฒฝ ๊ณผ: 00:01:00.50
- ์ปค๋ฐ์ด ์์ฃผ ๋ฐ์ํด ์ฑ๋ฅ๋ ์ ์ข์์ก์ผ๋, ํธ๋์ญ์ ์์์ฑ(Atomicity)์๋ ๋ฌธ์ ๊ฐ ์๊น
- ๋งค์ฐ ์ค๋ ๊ฑธ๋ฆฌ๋ ํธ๋์ญ์
์ ํ ๋ฒ๋ ์ปค๋ฐํ์ง ์๊ณ ์งํํ๋ฉด Undo ๊ณต๊ฐ ๋ถ์กฑ์ผ๋ก ์ธํด ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์
- ํธ๋์ญ์ ์์์ฑ์ ์ํด ๋ฐ๋์ ๊ทธ๋ ๊ฒ ์ฒ๋ฆฌํด์ผ ํ๋ค๋ฉด Undo ๊ณต๊ฐ์ ๋๋ ค์ผ
- ์๋๋ผ๋ฉด ์ ๋นํ ์ฃผ๊ธฐ๋ก ์ปค๋ฐ
-- ๋ฃจํ ์์ชฝ์ ์๋ ์ฝ๋ ์ถ๊ฐ
if mod(i, 100000) = 0 then -- 10๋ง ๋ฒ์ ํ ๋ฒ์ฉ ์ปค๋ฐ
commit;
end if;
public class JavaLoopQuery {
public void execute() throws Exception {
String SQLStmt = "select no, empno, ename, job, mgr"
+ ", to_char(hiredate, 'yyyymmdd hh24miss'), sal, comm, deptno "
+ "from source";
PreparedStatement stmt = con.prepareStatement(SQLStmt);
ResultSet rs = stmt.executeQuery();
while(rs.next()){
long no = rs.getLong(1);
long empno = rs.getLong(2);
String ename = rs.getString(3);
String job = rs.getString(4);
Integer mgr = rs.getInt(5);
String hiredate = rs.getString(6);
long sal = rs.getLong(7);
long comm = rs.getLong(8);
int deptno = rs.getInt(9);
insertTarget(con, no, empno, ename, job, mgr, hiredate, sal, comm, deptno);
}
rs.close();
stmt.close();
}
public void insertTarget( long p_no
, long p_empno
, String p_ename
, String p_job
, int p_mgr
, String p_hiredate
, long p_sal
, long p_comm
, int p_deptno) throws Exception {
String SQLStmt = "insert into target "
+ "(no, empno, ename, job, mgr, hiredate, sal, comm, deptno) "
+ "values (?, ?, ?, ?, ?, to_date(?, 'yyyymmdd hh24miss'), ?, ?, ?)";
PreparedStatement st = con.prepareStatement(SQLStmt);
st.setLong (1, p_no );
st.setLong (2, p_empno );
st.setString (3, p_ename );
st.setString (4, p_job );
st.setInt (5, p_mgr );
st.setString (6, p_hiredate);
st.setLong (7, p_sal );
st.setLong (8, p_comm );
st.setInt (9, p_deptno );
st.execute();
st.close();
}
...
...
}
/* ์ํ์๊ฐ 218.392์ด */
- ๋คํธ์ํฌ๋ฅผ ๊ฒฝ์ ํ๋ User Call์ด๋ฏ๋ก ์ฑ๋ฅ์ด ์ ์ข์
One SQL์ ์ค์์ฑ
SQL> insert into target
2 select * from source;
1000000 ๊ฐ์ ํ์ด ๋ง๋ค์ด์ก์ต๋๋ค.
๊ฒฝ ๊ณผ: 00:00:01.46
- ํ ๋ฒ์ Call๋ก ์ฒ๋ฆฌํ๋, ์ํ์๊ฐ์ด ๋น ๋ฆ
- ์ ๋ฌด ๋ก์ง์ด ๋ณต์กํ๋ฉด ์ ์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ๋ฐ์ ์์ง๋ง, ๊ฐ๊ธ์ One SQL๋ก ๊ตฌํํ๋ ค ๋ ธ๋ ฅํด์ผ ํจ
Array Processing ํ์ฉ
- One SQL๋ก ๊ตฌํํ๊ธฐ ๋ณต์กํ ์ ๋ฌด ๋ก์ง์ Array Processing ๊ธฐ๋ฅ์ ํ์ฉํ๋ฉด One SQL๋ก ๊ตฌํํ์ง ์๊ณ ๋ Call ๋ถํ๋ฅผ ์ค์ผ ์ ์์
SQL> declare
2 cursor c is select * from source;
3 type typ_source is table of c%rowtype;
4 l_source typ_source;
5
6 l_array_size number default 10000;
7
8 procedure insert_target( p_source in typ_source) is
9 begin
10 forall i in p_source.first..p_source.last
11 insert into target values p_source(i);
12 end insert_target;
13
14 begin
15 open c;
16 loop
17 fetch c bulk collect into l_source limit l_array_size;
18
19 insert_target( l_source );
20
21 exit when c%notfound;
22 end loop;
23
24 close c;
25
26 commit;
27 end;
28 /
๊ฒฝ ๊ณผ: 00:00:03.99
public class JavaArrayProcessing {
public void execute() throws Exception {
int arraySize = 10000;
long no [] = new long [arraySize];
long empno [] = new long [arraySize];
String ename [] = new String[arraySize];
String job [] = new String[arraySize];
int mgr [] = new int [arraySize];
String hiredate [] = new String[arraySize];
long sal [] = new long [arraySize];
long comm [] = new long [arraySize];
int deptno [] = new int [arraySize];
String SQLStmt = "select no, empno, ename, job, mgr"
+ ", to_char(hiredate, 'yyyymmdd hh24miss'), sal, comm, deptno "
+ "from source";
PreparedStatement st = con.prepareStatement(SQLStmt);
st.setFetchSize(arraySize);
ResultSet rs = st.executeQuery();
int i = 0;
while(rs.next()){
no [i] = rs.getLong(1);
empno [i] = rs.getLong(2);
ename [i] = rs.getString(3);
job [i] = rs.getString(4);
mgr [i] = rs.getInt(5);
hiredate[i] = rs.getString(6);
sal [i] = rs.getLong(7);
comm [i] = rs.getLong(8);
deptno [i] = rs.getInt(9);
if(++i == arraySize) { // 10,000๋ฒ์ ํ ๋ฒ์ฉ insertTarget ์คํ
insertTarget(i, no, empno, ename, job, mgr, hiredate, sal, comm, deptno);
i = 0;
}
}
if(i > 0) insertTarget(i, no, empno, ename, job, mgr, hiredate, sal, comm, deptno);
rs.close();
st.close();
}
public void insertTarget( int length
, long [] p_no
, long [] p_empno
, String[] p_ename
, String[] p_job
, int [] p_mgr
, String[] p_hiredate
, long [] p_sal
, long [] p_comm
, int [] p_deptno) throws Exception {
String SQLStmt = "insert into target "
+ "(no, empno, ename, job, mgr, hiredate, sal, comm, deptno) "
+ "values (?, ?, ?, ?, ?, to_date(?, 'yyyymmdd hh24miss'), ?, ?, ?)";
PreparedStatement st = con.prepareStatement(SQLStmt);
for(int i=0; i < length; i++){
st.setLong (1, p_no [i]);
st.setLong (2, p_empno [i]);
st.setString (3, p_ename [i]);
st.setString (4, p_job [i]);
st.setInt (5, p_mgr [i]);
st.setString (6, p_hiredate[i]);
st.setLong (7, p_sal [i]);
st.setLong (8, p_comm [i]);
st.setInt (9, p_deptno [i]);
st.addBatch(); // insert ํ ๊ฐ๋ค์ ๋ฐฐ์ด์ ์ ์ฅ
};
st.executeBatch(); // ๋ฐฐ์ด์ ์ ์ฅ๋ ๊ฐ์ ํ ๋ฒ์ insert
st.close();
}
...
...
}
/* ์คํ์๊ฐ 11.813์ด */
- ๋ง ๋ฒ์ ํ ๋ฒ์ฉ INSERT ํ๋๋ก ๊ตฌํํด ๋ฐฑ๋ง ๋ฒ ๋ฐ์ํ Call์ ๋ฐฑ ๋ฒ์ผ๋ก ์ค์
- Call์ ๋จ ํ๋๋ก ์ค์ด์ง ๋ชปํ๋๋ผ๋ Array Processing์ ํ์ฉํด ์ฑ๋ฅ ํฅ์์ด ๊ฐ๋ฅ
์ธ๋ฑ์ค ๋ฐ ์ ์ฝ ํด์ ๋ฅผ ํตํ ๋๋ DML ํ๋
- ์ธ๋ฑ์ค ๋ฐ ๋ฌด๊ฒฐ์ฑ ์ ์ฝ ์กฐ๊ฑด์ DML ์ฑ๋ฅ์ ํฐ ์ํฅ์ ๋ผ์นจ
- OLTP์์ ์ด๋ค ๊ธฐ๋ฅ์ ํด์ ํ ์๋ ์์
- ๋์ ํธ๋์ญ์ ์์ด ๋๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฌํ๋ ๋ฐฐ์น(Batch) ํ๋ก๊ทธ๋จ์์๋ ์ด๋ค์ ํด์ ํด ์ฑ๋ฅ๊ฐ์ ๊ฐ๋ฅ
-- ๋ฐ์ดํฐ 1000๋ง๊ฑด ์ถ๊ฐ ๋ฐ ์ธ๋ฑ์ค ์ค์
SQL> create table source
2 as
3 select b.no, a.*
4 from (select * from emp where rownum <= 10) a
5 ,(select rownum as no from dual connect by level <= 1000000) b;
SQL> create table target
2 as
3 select * from source where 1 = 2;
SQL> alter table target add
2 constraint target_pk primary key(no, empno);
SQL> create index target_x1 on target(ename);
SQL> set timing on;
SQL> insert /*+ append */ into target
2 select * from source;
10000000 ๊ฐ์ ํ์ด ๋ง๋ค์ด์ก์ต๋๋ค.
๊ฒฝ ๊ณผ: 00:01:19.10
SQL> commit;
PK ์ ์ฝ๊ณผ ์ธ๋ฑ์ค ํด์ 1 - PK ์ ์ฝ์ Unique ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ
-- PK์ ์ฝ๊ณผ ์ธ๋ฑ์ค ํด์
-- ์ธ๋ฑ์ค Drop
SQL> truncate table target;
SQL> alter table target modify constraint target_pk disable drop index;
SQL> alter index target_x1 unusable;
- ์ผ๋ฐ ์ธ๋ฑ์ค๋ Unusable ์ํ๋ก ๋ณ๊ฒฝ
SQL> insert /*+ append */ into target
2 select * from source;
10000000 ๊ฐ์ ํ์ด ๋ง๋ค์ด์ก์ต๋๋ค.
๊ฒฝ ๊ณผ: 00:00:05.84
SQL> commit;
SQL> alter table target modify constraint target_pk enable NOVALIDATE;
๊ฒฝ ๊ณผ: 00:00:06.77
SQL> alter index target_x1 rebuild;
๊ฒฝ ๊ณผ: 00:00:08.26
- ๋ฐ์ดํฐ ์
๋ ฅ ๋ฐ ์ ์ฝ ํ์ฑํ & ์ธ๋ฑ์ค ์ฌ์์ฑ ์๊ฐ์ ํฉ์ณ๋ ๊ธฐ์กด๋ณด๋ค ํจ์ฌ ๋น ๋ฆ
- PK๋ฅผ ํ์ฑํํ๋ฉด์ NOVALIDATE ์ต์
์ ์ฌ์ฉํ ๊ฒ๋ ์ํฅ์ด ํผ
- ์ฌ์ฉํ์ง ์๋๋ค๋ฉด, ๋ฌด๊ฒฐ์ฑ ์ฒดํฌ๋ฅผ ํด์ผ ํจ
- PK๋ฅผ ํ์ฑํํ๋ฉด์ NOVALIDATE ์ต์
์ ์ฌ์ฉํ ๊ฒ๋ ์ํฅ์ด ํผ
PK ์ ์ฝ๊ณผ ์ธ๋ฑ์ค ํด์ 1 - PK ์ ์ฝ์ Non-Unique ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ
- X1 ์ธ๋ฑ์ค๋ Unusable ์ํ๋ก ๋ณ๊ฒฝํ์ง๋ง, PK ์ธ๋ฑ์ค๋ ์ ์ฝ์ ๋นํ์ฑํํ๋ฉด์ Drop ํ์
- PK๋ Unusable ์ํ์์ ๋ฐ์ดํฐ ์ ๋ ฅ ๋ถ๊ฐ
- PK๋ฅผ Dropํ์ง ์๊ณ Unusable ์ํ์์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅํ๊ณ ์ถ๋ค๋ฉด, PK ์ ์ฝ์ Non-Unique ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉ
SQL> set timing off;
SQL> truncate table target;
SQL> alter table target drop primary key drop index;
SQL> create index target_pk on target(no, empno); -- Non-Unique ์ธ๋ฑ์ค ์์ฑ
SQL> alter table target add
2 constraint target_pk primary key (no, empno)
3 using index target_pk; -- PK ์ ์ฝ์ Non-Unique ์ธ๋ฑ์ค ์ฌ์ฉํ๋๋ก ์ง์
SQL> alter table target modify constraint target_pk disable keep index;
SQL> alter index target_pk unusable;
SQL> alter index target_x1 unusable;
SQL> set timing on;
SQL> insert /*+ append */ into target
2 select * from source;
10000000 ๊ฐ์ ํ์ด ๋ง๋ค์ด์ก์ต๋๋ค.
๊ฒฝ ๊ณผ: 00:00:05.53
SQL> commit;
๊ฒฝ ๊ณผ: 00:00:00.00
SQL> alter index target_x1 rebuild;
๊ฒฝ ๊ณผ: 00:00:07.24
SQL> alter index target_pk rebuild;
๊ฒฝ ๊ณผ: 00:00:05.27
SQL> alter table target modify constraint target_pk enable novalidate;
๊ฒฝ ๊ณผ: 00:00:00.06
์์ ๊ฐ๋ฅ ์กฐ์ธ ๋ทฐ
update ๊ณ ๊ฐ c
set ์ต์ข
๊ฑฐ๋์ผ์ = (select max(๊ฑฐ๋์ผ์) from ๊ฑฐ๋
where ๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1)))
, ์ต๊ทผ๊ฑฐ๋ํ์ = (select count(*) from ๊ฑฐ๋
where ๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1)))
, ์ต๊ทผ๊ฑฐ๋๊ธ์ก = (select sum(๊ฑฐ๋๊ธ์ก) from ๊ฑฐ๋
where ๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1)))
where exists (select 'x' from ๊ฑฐ๋
where ๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1)))
-- ์ด๋ ๊ฒ ์์ ๊ฐ๋ฅ
update ๊ณ ๊ฐ c
set (์ต์ข
๊ฑฐ๋์ผ์, ์ต๊ทผ๊ฑฐ๋ํ์, ์ต๊ทผ๊ฑฐ๋๊ธ์ก) =
(select max(๊ฑฐ๋์ผ์), count(*), sum(๊ฑฐ๋๊ธ์ก)
from ๊ฑฐ๋
where ๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1)))
where exists (select 'x' from ๊ฑฐ๋
where ๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1)))
- ์์ ํ ๋ฐฉ์๋, ํ ๋ฌ ์ด๋ด ๊ณ ๊ฐ๋ณ ๊ฑฐ๋ ๋ฐ์ดํฐ๋ฅผ 2๋ฒ ์กฐํํ๊ธฐ ๋๋ฌธ์ ๋นํจ์จ์ด ์๊ธด ํจ
- ์ด ๊ณ ๊ฐ ์์ ํ ๋ฌ ์ด๋ด ๊ฑฐ๋ ๊ณ ๊ฐ ์์ ๋ฐ๋ผ ์ฑ๋ฅ ์ข์ฐ
update ๊ณ ๊ฐ c
set (์ต์ข
๊ฑฐ๋์ผ์, ์ต๊ทผ๊ฑฐ๋ํ์, ์ต๊ทผ๊ฑฐ๋๊ธ์ก) =
(select max(๊ฑฐ๋์ผ์), count(*), sum(๊ฑฐ๋๊ธ์ก)
from ๊ฑฐ๋
where ๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1)))
where exists (select /*+ unnest hash_sj */ 'x' from ๊ฑฐ๋
where ๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1)))
- ์ด ๊ณ ๊ฐ ์๊ฐ ์์ฃผ ๋ง๋ค๋ฉด Exists ์๋ธ์ฟผ๋ฆฌ๋ฅผ ํด์ ์ธ๋ฏธ ์กฐ์ธ์ผ๋ก ์ ๋ํ๋ ๊ฒ์ ๊ณ ๋ ค
update ๊ณ ๊ฐ c
set (์ต์ข
๊ฑฐ๋์ผ์, ์ต๊ทผ๊ฑฐ๋ํ์, ์ต๊ทผ๊ฑฐ๋๊ธ์ก) =
(select nvl(max(๊ฑฐ๋์ผ์), c.์ต์ข
๊ฑฐ๋์ผ์)
, decode(count(*), 0, c.์ต๊ทผ๊ฑฐ๋ํ์, count(*))
, nvl(sum(๊ฑฐ๋๊ธ์ก), c.์ต๊ทผ๊ฑฐ๋๊ธ์ก)
from ๊ฑฐ๋
where ๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1)))
- ํ ๋ฌ ์ด๋ด ๊ฑฐ๋๋ฅผ ๋ฐ์์ํจ ๊ณ ๊ฐ์ด ๋ง์ UPDATE ๋ฐ์๋์ด ๋ง๋ค๋ฉด, ์์ ๊ฐ์ด ๋ณ๊ฒฝ ๊ฐ๋ฅ
- ํ์ง๋ง ๋ชจ๋ ๊ณ ๊ฐ ๋ ์ฝ๋์ LOCK์ด ๊ฑธ๋ฆผ
- ์ด์ ๊ณผ ๊ฐ์ ๊ฐ์ ๊ฐฑ์ ๋๋ ๋น์ค์ด ๋์์๋ก Redo ๋ก๊ทธ ๋ฐ์๋์ด ์ฆ๊ฐํด ๋นํจ์จ์ ์ผ ์ ์์
- ๋ค๋ฅธ ํ ์ด๋ธ๊ณผ ์กฐ์ธ์ด ํ์ํ ๋ ์ ํต์ ์ธ UPDATE ๋ฌธ์ ์ฌ์ฉํ๋ฉด ๋นํจ์จ์ ์์ ํ ํด์ํ ์ ์์
์์ ๊ฐ๋ฅ ์กฐ์ธ ๋ทฐ
- ์์ ๊ฐ๋ฅ ์กฐ์ธ ๋ทฐ๋ฅผ ํ์ฉํ๋ฉด ์ฐธ์กฐ ํ ์ด๋ธ๊ณผ ๋ ๋ฒ ์กฐ์ธํ๋ ๋นํจ์จ์ ์์จ ์ ์์
update
( select /*+ ordered use_hash(c) no_merge(t) */
c.์ต์ข
๊ฑฐ๋์ผ์, c.์ต๊ทผ๊ฑฐ๋ํ์, c.์ต๊ทผ๊ฑฐ๋๊ธ์ก
, t.๊ฑฐ๋์ผ์, t.๊ฑฐ๋ํ์, t.๊ฑฐ๋๊ธ์ก
from (select ๊ณ ๊ฐ๋ฒํธ
, max(๊ฑฐ๋์ผ์) ๊ฑฐ๋์ผ์, count(*) ๊ฑฐ๋ํ์, sum(๊ฑฐ๋๊ธ์ก) ๊ฑฐ๋๊ธ์ก
from ๊ฑฐ๋
where ๊ฑฐ๋์ผ์ >= trunc(add_months(sysdate, -1))
group by ๊ณ ๊ฐ๋ฒํธ) t
, ๊ณ ๊ฐ c
where c.๊ณ ๊ฐ๋ฒํธ = t.๊ณ ๊ฐ๋ฒํธ
)
set ์ต์ข
๊ฑฐ๋์ผ์ = ๊ฑฐ๋์ผ์
, ์ต๊ทผ๊ฑฐ๋ํ์ = ๊ฑฐ๋ํ์
, ์ต๊ทผ๊ฑฐ๋๊ธ์ก = ๊ฑฐ๋๊ธ์ก
- ์กฐ์ธ ๋ทฐ๋ FROM ์ ์ ๋ ๊ฐ ์ด์ ํ
์ด๋ธ์ ๊ฐ์ง ๋ทฐ
- ์์ ๊ฐ๋ฅ ์กฐ์ธ ๋ทฐ๋ ์
๋ ฅ/์์ /์ญ์ ๊ฐ ํ์ฉ๋๋ ์กฐ์ธ ๋ทฐ
- 1์ชฝ ์งํฉ๊ณผ ์กฐ์ธํ๋ M์ชฝ ์งํฉ์๋ง ํ์ฉ
- ์์ ๊ฐ๋ฅ ์กฐ์ธ ๋ทฐ๋ ์
๋ ฅ/์์ /์ญ์ ๊ฐ ํ์ฉ๋๋ ์กฐ์ธ ๋ทฐ
SQL> create table emp as select * from scott.emp;
SQL> create table dept as select * from scott.dept;
SQL> create or replace view EMP_DEPT_VIEW as
2 select e.rowid emp_rid, e.*, d.rowid dept_rid, d.dname, d.loc
3 from emp e, dept d
4 where e.deptno = d.deptno;
SQL> update EMP_DEPT_VIEW set loc = 'SEOUL' where job = 'CLERK';
- job = 'CLERK'์ธ ์ฌ์์ด ๋ถ์ 10, 20, 30์ ๋ชจ๋ ์ํด ์๋๋ฐ, UPDATE๋ฅผ ์ํํ๊ณ ๋๋ฉด ์ธ ๋ถ์์ ์์ฌ์ง๊ฐ ๋ชจ๋ SEOUL๋ก ๋ฐ๋
- ํ์ง๋ง ๋ค๋ฅธ job์ ๊ฐ์ง ์ฌ์์ ๋ถ์ ์์ฌ์ง๊น์ง ๋ฐ๋๋ ๊ฒ์ ์ํ๋ ๊ฒฐ๊ณผ๋ ์๋
-- ORA-01779: cannot modify a column which maps to a non key-preserved table ์๋ฌ ๋ฐ์
SQL> update EMP_DEPT_VIEW set comm = nvl(comm, 0) + (sal * 0.1) where sal <= 1500;
-- ORA-01752: cannot delete from view without exactly one key-preserved table ์๋ฌ ๋ฐ์
SQL> delete from EMP_DEPT_VIEW where job = 'CLERK';
- ์ตํฐ๋ง์ด์ ๊ฐ ์ด๋ ํ ์ด๋ธ์ด 1์ชฝ ์งํฉ์ธ์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ ์๋ฌ
- 1์ชฝ ์งํฉ์ PK ์ ์ฝ์ ์ค์ ํ๊ฑฐ๋ Unique ์ธ๋ฑ์ค๋ฅผ ์์ฑํด์ผ ์์ ๊ฐ๋ฅ ์กฐ์ธ๋ทฐ๋ฅผ ํตํ ์ ๋ ฅ/์์ /์ญ์ ๊ฐ๋ฅ
SQL> alter table dept add constraint dept_pk primary key(deptno);
SQL> update EMP_DEPT_VIEW set comm = nvl(comm, 0) + (sal * 0.1) where sal <= 1500;
4 rows updated.
- PK ์ ์ฝ์ ์ค์ ํ๋ฉด EMP ํ ์ด๋ธ์ *ํค-๋ณด์กด ํ ์ด๋ธ(Key-Preserved Table)*์ด ๋๊ณ , DEPT ํ ์ด๋ธ์ *๋น ํค-๋ณด์กด ํ ์ด๋ธ(Non Key-Preserved Table)*๋ก ๋จ์
ํค ๋ณด์กด ํ ์ด๋ธ
- ์กฐ์ธ๋ ๊ฒฐ๊ณผ์งํฉ์ ํตํด์๋ ์ค๋ณต ๊ฐ ์์ด Uniqueํ๊ฒ ์๋ณ์ด ๊ฐ๋ฅํ ํ
์ด๋ธ
- Uniqueํ 1์ชฝ ์งํฉ๊ณผ ์กฐ์ธ๋๋ ํ ์ด๋ธ์ด์ด์ผ ์กฐ์ธ๋ ๊ฒฐ๊ณผ์งํฉ์ ํตํ ์๋ณ์ด ๊ฐ๋ฅ
SQL> select ROWID, emp_rid, dept_rid, empno, deptno from EMP_DEPT_VIEW;
ROWID EMP_RID DEPT_RID EMPNO DEPTNO
------------------ ------------------ ------------------ ------ --------
AAAMt4AAGAAAEWSAAA AAAMt4AAGAAAEWSAAA AAAMt5AAGAAAEWaAAB 7369 20
AAAMt4AAGAAAEWSAAB AAAMt4AAGAAAEWSAAB AAAMt5AAGAAAEWaAAC 7499 30
AAAMt4AAGAAAEWSAAC AAAMt4AAGAAAEWSAAC AAAMt5AAGAAAEWaAAC 7521 30
AAAMt4AAGAAAEWSAAD AAAMt4AAGAAAEWSAAD AAAMt5AAGAAAEWaAAB 7566 20
AAAMt4AAGAAAEWSAAE AAAMt4AAGAAAEWSAAE AAAMt5AAGAAAEWaAAC 7654 30
AAAMt4AAGAAAEWSAAG AAAMt4AAGAAAEWSAAG AAAMt5AAGAAAEWaAAA 7782 10
...... ...... ...... ... ...
14 rows selected.
- dept_rid ์ค๋ณต์ด ๋ํ๋ค๊ณ ์๊ณ , emp_rid๋ ์ค๋ณต ๊ฐ์ด ์์ผ๋ฉฐ ๋ทฐ์ rowid์ ์ผ์น
- ํค ๋ณด์กด ํ ์ด๋ธ์ด๋ ๋ทฐ์ rowid๋ฅผ ์ ๊ณตํ๋ ํ ์ด๋ธ
- DEPT ํ ์ด๋ธ๋ก๋ถํฐ Unique ์ธ๋ฑ์ค๋ฅผ ์ ๊ฑฐํ๋ฉด ํค ๋ณด์กด ํ ์ด๋ธ์ด ์๊ธฐ ๋๋ฌธ์ ๋ทฐ์์ rowid ์ถ๋ ฅ ๋ถ๊ฐ
SQL> alter table dept drop primary key;
-- ORA-01445: cannot select ROWID from, or sample, a join view without a key-preserved table
SQL> select rowid, emp_rid, dept_rid, empno, deptno from EMP_DEPT_VIEW;
ORA-01779 ์ค๋ฅ ํํผ
SQL> alter table dept add avg_sal number(7,2);
-- ORA-01779: cannot modify a column which maps to a non key-preserved table
SQL> update
2 (select d.deptno, d.avg_sal as d_avg_sal, e.avg_sal as e_avg_sal
3 from (select deptno, round(avg(sal), 2) avg_sal from emp group by deptno) e
4 , dept d
5 where d.deptno = e.deptno )
6 set d_avg_sal = e_avg_sal ;
- 11g ์ดํ ๋ฒ์ ์์ ORA-01779 ์๋ฌ ๋ฐ์
- EMP ํ ์ด๋ธ์ DEPTNO๋ก Group By ํ์ผ๋ฏ๋ก DEPTNO ์ปฌ๋ผ์ผ๋ก ์กฐ์ธํ DEPT ํ ์ด๋ธ์ ํค๊ฐ ๋ณด์กด๋๋๋ฐ๋ ์ตํฐ๋ง์ด์ ๊ฐ ๋ถํ์ํ ์ ์ฝ์ ๊ฐํ ๊ฒ
SQL> update /*+ bypass_ujvc */
2 (select d.deptno, d.avg_sal d_avg_sal, e.avg_sal e_avg_sal
3 from (select deptno, round(avg(sal), 2) avg_sal from emp group by deptno) e
4 , dept d
5 where d.deptno = e.deptno )
6 set d_avg_sal = e_avg_sal ;
- 10g์์ bypass_ujvc ํํธ๋ก ์ ์ฝ ํํผ ๊ฐ๋ฅ
- 11g๋ถํฐ๋ MERGE ๋ฌธ์ผ๋ก ๋ณ๊ฒฝํด์ผ ํจ
- bypass_ujvc ํํธ ์ฌ์ฉ์ด ๋ถ๊ฐํ ๋ฟ, ์์ ๊ฐ๋ฅ ์กฐ์ธ ๋ทฐ ์ฌ์ฉ์ด ์ค๋จ๋ ๊ฒ์ ์๋
- 1์ชฝ ์งํฉ์ Unique ์ธ๋ฑ์ค๊ฐ ์๋ค๋ฉด, ์์ ๊ฐ๋ฅ ์กฐ์ธ ๋ทฐ๋ฅผ ์ด์ฉํ UPDATE๊ฐ ๊ฐ๋ฅ
-- ์ด๋ค ๋ฒ์ ์์๋ ์คํ ๋ถ๊ฐ
update (
select o.์ฃผ๋ฌธ๊ธ์ก, o.ํ ์ธ๊ธ์ก, c.๊ณ ๊ฐ๋ฑ๊ธ
from ์ฃผ๋ฌธ_t o, ๊ณ ๊ฐ_t c
where o.๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and o.์ฃผ๋ฌธ๊ธ์ก >= 1000000
and c.๊ณ ๊ฐ๋ฑ๊ธ = 'A')
set ํ ์ธ๊ธ์ก = ์ฃผ๋ฌธ๊ธ์ก * 0.2, ์ฃผ๋ฌธ๊ธ์ก = ์ฃผ๋ฌธ๊ธ์ก * 0.8
-- 12c์์๋ ์๋์ ๊ฐ์ด ๊ฐ๋ฅ
update (
select o.์ฃผ๋ฌธ๊ธ์ก, o.ํ ์ธ๊ธ์ก
from ์ฃผ๋ฌธ_t o
, (select ๊ณ ๊ฐ๋ฒํธ from ๊ณ ๊ฐ_t where ๊ณ ๊ฐ๋ฑ๊ธ = 'A' group by ๊ณ ๊ฐ๋ฒํธ) c
where o.๊ณ ๊ฐ๋ฒํธ = c.๊ณ ๊ฐ๋ฒํธ
and o.์ฃผ๋ฌธ๊ธ์ก >= 1000000)
set ํ ์ธ๊ธ์ก = ์ฃผ๋ฌธ๊ธ์ก * 0.2, ์ฃผ๋ฌธ๊ธ์ก = ์ฃผ๋ฌธ๊ธ์ก * 0.8
MERGE๋ฌธ ํ์ฉ
- MERGE๋ฌธ์ Source ํ
์ด๋ธ ๊ธฐ์ค์ผ๋ก Target ํ
์ด๋ธ๊ณผ Left Outer ๋ฐฉ์์ผ๋ก ์กฐ์ธํด์ ์ฑ๊ณตํ๋ฉด UPDATE, ์คํจํ๋ฉด INSERT๋ฅผ ํจ
- UPSERT๋ผ๊ณ ๋ ๋ถ๋ฆ
Optional Clauses
-- UPDATE/INSERT๋ฅผ ์ ํ์ ์ผ๋ก ์ฒ๋ฆฌ
merge into customer t using customer_delta s on (t.cust_id = s.cust_id)
when matched then update
set t.cust_nm = s.cust_nm, t.email = s.email, ... ;
merge into customer t using customer_delta s on (t.cust_id = s.cust_id)
when not matched then insert
(cust_id, cust_nm, email, tel_no, region, addr, reg_dt) values
(s.cust_id, s.cust_nm, s.email, s.tel_no, s.region, s.addr, s.reg_dt);
-- ์์ ๊ฐ๋ฅ ์กฐ์ธ๋ทฐ
update
(select d.deptno, d.avg_sal as d_avg_sal, e.avg_sal as e_avg_sal
from (select deptno, round(avg(sal), 2) avg_sal from emp group by deptno) e
, dept d
where d.deptno = e.deptno )
set d_avg_sal = e_avg_sal ;
-- MERGE๋ก ๋์ฒด ๊ฐ๋ฅ
merge into dept d
using (select deptno, round(avg(sal), 2) avg_sal from emp group by deptno) e
on (d.deptno = e.deptno)
when matched then update set d.avg_sal = e_avg_sal;
Conditional Operations
-- on ์ ์ ๊ธฐ์ ํ ์กฐ์ธ๋ฌธ ์ธ์ ์ถ๊ฐ๋ก ์กฐ๊ฑด์ ๊ธฐ์ ๊ฐ๋ฅ
merge into customer t using customer_delta s on (t.cust_id = s.cust_id)
when matched then update
set t.cust_nm = s.cust_nm, t.email = s.email, ...
where reg_dt >= to_date('20000101', 'yyyymmdd')
when not matched then insert
(cust_id, cust_nm, email, tel_no, region, addr, reg_dt) values
(s.cust_id, s.cust_nm, s.email, s.tel_no, s.region, s.addr, s.reg_dt)
where reg_dt < trunc(sysdate) ;
DELETE Clause
merge into customer t using customer_delta s on (t.cust_id = s.cust_id)
when matched then
update set t.cust_nm = s.cust_nm, t.email = s.email, ...
delete where t.withdraw_dt is not null -- ํํด์ผ์๊ฐ null์ด ์๋ ๋ ์ฝ๋ ์ญ์
when not matched then insert
(cust_id, cust_nm, email, tel_no, region, addr, reg_dt) values
(s.cust_id, s.cust_nm, s.email, s.tel_no, s.region, s.addr, s.reg_dt);
- MERGE๋ฌธ์์ UPDATE๊ฐ ์ด๋ค์ง ๊ฒฐ๊ณผ๋ก์ withdraw_dt๊ฐ NULL์ด ์๋ ๋ ์ฝ๋๋ง ์ญ์
- withdraw_dt๊ฐ NULL์ด ์๋์์ด๋, MERGE๋ฌธ์ ์ํํ ๊ฒฐ๊ณผ๊ฐ NULL์ด๋ฉด ์ญ์ ํ์ง ์์
- MERGE๋ฌธ DELETE ์ ์ ์กฐ์ธ์ ์ฑ๊ณตํ ๋ฐ์ดํฐ๋ง ์ญ์ ๊ฐ๋ฅ
- Source์์ ์ญ์ ๋ ๋ฐ์ดํฐ๋ฅผ Target์์ ์ง์ฐ๋ ์ญํ ๊น์ง ๋ชปํจ
- Source์์ ์ญ์ ๋ ๋ฐ์ดํฐ๋ ์กฐ์ธ์ ์คํจํ๊ธฐ ๋๋ฌธ
- Source์์ ์ญ์ ๋ ๋ฐ์ดํฐ๋ฅผ Target์์ ์ง์ฐ๋ ์ญํ ๊น์ง ๋ชปํจ
ํ์ฉ ์์
-- SQL์ ํญ์ 2๋ฒ์ฉ ์ํ
select count(*) into :cnt from dept where deptno = :val1;
if :cnt = 0 then
insert into dept(deptno, dname, loc) values(:val1, :val2, :val3);
else
update dept set dname = :val2, loc = :val3 where deptno = :val1;
end if;
-- ์ด ๊ฒฝ์ฐ, SQL์ ์ต๋ 2๋ฒ์ฉ ์ํ
update dept set dname = :val2, loc = :val3 where deptno = :val1;
if sql%rowcount = 0 then
insert into dept(deptno, dname, loc) values(:val1, :val2, :val3);
end if;
-- ์ด ๊ฒฝ์ฐ, SQL์ ํ ๋ฒ๋ง ์ํ
merge into dept a
using (select :val1 deptno, :val2 dname, :val3 loc from dual) b
on (b.deptno = a.deptno)
when matched then
update set dname = b.dname, loc = b.loc
when not matched then
insert (a.deptno, a.dname, a.loc) values (b.deptno, b.dname, b.loc);
์์ ๊ฐ๋ฅ ์กฐ์ธ ๋ทฐ vs MERGE ๋ฌธ
- ์คํ๊ณํ๋ง ๊ฐ๋ค๋ฉด UPDATE๋ MERGE๋ ์๊ด ์์
MERGE INTO EMP T2
USING (SELECT T.ROWID AS RID, S.ENAME
FROM EMP T, EMP_SRC S
WHERE T.EMPNO = S.EMPNO
AND T.ENAME <> S.ENAME) S
ON (T2.ROWID = S.RID)
WHEN MATCHED THEN UPDATE SET T2.ENAME = S.ENAME;
- ์ ํจํด์ UPDATE ๋์ ๊ฑด์๋ฅผ ์ฝ๊ฒ ํ์ธ ๊ฐ๋ฅ
- SELECT ๋ฌธ์ ๋จผ์ ๋ง๋ค์ด ๋ฐ์ดํฐ ๊ฒ์ฆ์ ๋ง์น ํ, ๋ฐ๊นฅ์ MERGE๋ฌธ ์ฌ์ฉ
- ON ์ ์ ROWID ์ฌ์ฉ
- ๊ทธ๋ฌ๋ UPDATE ๋์ ํ
์ด๋ธ์ธ EMP๋ฅผ ๋ ๋ฒ ์์ธ์คํ๋ฏ๋ก ์ฑ๋ฅ์ด ์ ์ข์
- ON์ ์ ROWID๋ฅผ ์ฌ์ฉํ์ผ๋ฏ๋ก ๋ฌธ์ ๊ฐ ์๋ค๊ณ ์๊ฐํ ์ ์์ง๋ง, ROWID๋ ํฌ์ธํฐ๊ฐ ์๋
-- ์ฑ๋ฅ์ ๊ณ ๋ คํ๋ฉด, ์๋์ ๊ฐ์ด ์์ฑํด์ผ ํจ
-- ๋ฐ์ดํฐ ๊ฒ์ฆ์ฉ SELECT ๋ฌธ์ ๋ฐ๋ก ํ๋ ๋ ๋ง๋ค์ด์ผ ํจ
MERGE INTO EMP T
USING EMP_SRC S
ON (T.EMPNO = S.EMPNO)
WHEN MATCHED THEN UPDATE SET T.ENAME = S.ENAME
WHERE T.ENAME <> S.ENAME;
-- ์์ ๊ฐ๋ฅ ์กฐ์ธ๋ทฐ๊ฐ ๋ ํธํ ์ ์์
-- SELECT๋ฌธ ๋จผ์ ๋ง๋ค์ด ๋ฐ์ดํฐ ๊ฒ์ฆ์ ๋ง์น ํ, ๋ฐ๊นฅ์ UPDATE
UPDATE (
SELECT S.ENAME AS S_ENAME, T.ENAME AS T_ENAME
FROM EMP T, EMP_SRC S
WHERE T.EMPNO = S.EMPNO
AND T.ENAME <> S.ENAME
)
SET T_ENAME = S_ENAME;
- EMP_SRC ํ
์ด๋ธ EMPNO ์ปฌ๋ผ์ Unique ์ธ๋ฑ์ค๊ฐ ์์ฑ๋ผ ์์ด์ผ ํจ
- ์๋ค๋ฉด 10g๊น์ง๋ bypass_ujvc, 12c๋ถํฐ๋ Group By ์ฒ๋ฆฌ๋ก ORA-01779 ํํผ ๊ฐ๋ฅ