
파티션을 활용한 대량 UPDATE 튜닝
인덱스가 DML 성능에 큰 영향을 미치기때문에 대량 데이터를 CRUD 할때는 인덱스를 DROP 하거나 UNUSABLE 상태로 변경한 후 작업하는 방법을 활용합니다. CRUD 할 데이터의 비중이 전체의 5% 를 넘으면 인덱스 없이 작업한 후 재생성하는 것이 유리합니다.
-- 거래테이블이 10억건이 저장돼있을때 UPDATE 문을 이용해 2015년 1월 1일 전에 발생한 거래 데이터를 수정하려힙니다.
-- 거래 일자 조건을 만족하면서 상태코드가 'ZZZ 가 아닌 데이터가 5000만 건 일때, 테이블 레코드 5000만 건을 변경하면서 거래_X2 인덱스 까지 실시간으로 관리하려면 많은 시간이 소요됩니다.
update 거래 set 상태코드 = 'ZZZ'
where 상태코드 <> 'ZZZ'
and 거래일자 < '20150101'
파티션 EXCHANGE를 이용한 대량 데이터 변경
파티셔닝 된 테이블의 인덱스가 로컬 인덱스라면 수정된 값을 임시 세그먼트로 만들어 원본 파티션과 바꿔치기 하는 방식을 사용할 수 있습니다. 작업순서는 다음과 같습니다.
-- 1. 수정 데이터 저장을 위한 임시 테이블을 생성합니다. 되도록 nologging 모드로 생성합니다.
CREATE TABLE 거래_T
NOLOGGING
AS
SELECT * FROM 거래 WHERE 1=2;
-- 2. 거래 데이블의 변경대상 데이터를 읽어 임시 테이블에 입력하면서 상태코드 값을 수정합니다
INSERT INTO 거래_T
SELECT 고객번호, 거래일자, 거래순번, ... , (CASE WHEN 상태코드 <> 'ZZZ' ELSE 상태코드 END ) 상태코드
FROM 거래
WHERE 거래일자 < '20150101';
-- 3. 원본 테이블의 인덱스와 같은 구조로 임시 테이블의 인덱스를 생성합니다. 되도록 nologging 모드로 생성합니다.
create unique index 거래_t_pk on 거래_t (고객번호, 거래일자, 거래순번) nologging;
create index 거래_t_x1 on 거래_t(거래일자, 고객번호) nologging;
create index 거래_t_x2 on 거래_t(상태코드, 거래일자) nologging;
-- 4. 값의 범위가 2014년 12월 인 파티션과 임시 테이블을 교체합니다.
alter table 거래
exchange partition p201412 with table 거래_t
including indexes without validation;
-- 5. 임시 테이블을 DROP 합니다.
drop table 거래_t;
-- 6. 파티션을 logging 모드로 전환합니다.
alter table 거래 modify partition p201412 logging;
alter index 거래_pk modify partition p201412 logging;
alter index 거래_x1 modify partition p201412 logging;
alter index 거래_x2 modify partition p201412 logging;
파티션을 활용한 대량 DELETE 튜닝
대량의 데이터를 삭제할때도 인덱스를 실시간으로 관리하면 많은 시간이 소모됩니다.
delete from 거래
where 거래일자 < '20150101'
DELETE 연산은 아래와 같은 부수작업을 동반하므로 느립니다.
- 테이블 레코드 삭제
- 테이블 레코드 삭제에 대한 UNDO LOGGING
- 테이블 레코드 삭제에 대한 REDO LOGGING
- 인덱스 레코드 삭제
- 인덱스 레코드 삭제에 대한 UNDO LOGGING
- 인덱스 레코드 삭제에 대한 REDO LOGGING
- UNDO에 대한 REDO LOGGING
추가적으로, 각 인덱스 레코드를 찾아가는 수직 탐색이 발생합니다.
파티션 DROP을 이용한 대량 데이터 삭제
테이블이 삭제 조건절(거래일자)을 기준으로 파티셔닝되어 있고 인덱스가 로컬 파티션이라면 파티션 DROP 을 통해 아주 빠르게 대량데이터를 삭제할 수 있습니다.
alter table 거래 drop partition p201412;
-- 오라클 11g 부터 아래와 같이 값을 이용해 대상 파티션을 지정할 수도 있습니다.
alter table 거래 drop partition for ('20141201')
파티션 TRUNCATE 를 이용한 대량 데이터 삭제
삭제할 데이터가 대량데이터라면 삭제하지 않을 데이터만 백업했다가 재입력하는 방식을 고려할 수 있습니다.
-- 1. 임시 테이블을 생성해 남길 데이터만 복제합니다.
create table t
as
select *
from 거래
where 거래일자 >= '20150101'
and 상태코드 = 'ZZZ'
-- 2. 삭제 대상 테이블 파티션을 TRUNCATE 합니다.
alter table 거래 truncate partition p201412;
-- 오라클 11g 부터 아래와 같이 값을 이용해 대상 파티션을 지정할 수 있습니다.
alter table 거래 truncate partition for ('20141201');
-- 3. 임시 테이블의 데이터를 원본 테이블에 복제합니다.
insert into 거래
select * from 거래_t;
-- 4. 임시 테이블을 drop 합니다.
drop table 거래_t;
서비스의 중단 없이 파티션을 DROP 혹은 TRUNCATE 하려면 아래 조건을 모두 만족해야 합니다.
- 파티션 키와 조건 컬럼이 일치해야합니다.
- 파티션 단위와 조건 컬럼의 단위가 일치히야 합니다.
- 모든 인덱스가 로컬 파티션 인덱스여야 합니다.
파티션을 활용한 대량 INSERT 튜닝
비파티션 테이블의 경우
비파티션 테이블에 손익분기점이 넘는 대량 데이터를 INSERT 하려면, 인덱스를 UNUSABLE 했다가 복구하는 방식이 더 효율적일 수 있습니다.
alter table target_t nologging
-- 인덱스를 unusable 상태로 전환한다.
alter index target_t_x01 unusable;
-- append 힌트를 통해 DIRECT PATH INSERT 방식으로 대량 데이터를 입력합니다.
insert /*+append*/ into target_t
select * from source_t
-- 테이블을 nologging 모드로 한 후 인덱스를 재생성합니다.
alter index target_t_x01 rebuild nologging
-- nologging 상태인 테이블과 인덱스를 logging 상태로 복구합니다.
alter table target_x logging;
alter index target_t_x01 logging;
파티션 테이블의 경우
초대용량 인덱스의 경우 재생성하는 부담이 크기때문에 인덱스를 그대로 둔 상태에서 INSERT 하는 것이 좋습니다. 테이블이 파티셔닝 상태여야하고 인덱스도 로컬 파티션 인덱스라면 가장 효율적입니다. 파티션 단위로 인덱슬르 재생성할 수 있기 때문입니다.
-- 데이터 입력 대상 파티션을 Nologging 모드로 변경합니다.
alter table target modify partition p_201712 nologging;
-- 해당 파티션과 메칭되는 인덱스 파티션을 비활성화 합니다.
alter index target_t_x01 modify partition p_201712 unusable;
-- 초대량 데이터를 DIRECT PATH INDSET 방식으로 대량 데이터를 입력합니다.
insert /*+append*/ into target_t
select * from source_t where dt between '20171201' and '20171231';
-- 테이블이 Nologging인 상태에서 인덱스 파티션을 재생성합니다.
alter index target_t_x01 rebuild partition p_201712 nologging
-- nologging 상태의 테이블 파티션과 인덱스 파티션을 logging 모드로 전환합니다.
alter table target_t modify partiton p_201712 logging;
alter index taret_t_x01 modify partiton p_201712 logging;
# exchanging partition
# drop partition for
# truncate partition
# modify partition
# rebuild partition
'DB > SQL튜닝' 카테고리의 다른 글
| SQL튜닝이론 - 트랜잭션의 블로킹 해소를 위한 COMMIT (0) | 2024.02.11 |
|---|---|
| SQL 튜닝이론 - 데이터 정합성을 위한 다양한 LOCK (0) | 2024.02.11 |
| SQL튜닝이론 - 인덱스 파티셔닝을 통한 DML 성능향상 LOCAL PREFIXED, LOCAL NONPREFIXED, GLOBAL PREFIXED, 비파티션 인덱스 (0) | 2024.02.07 |
| SQL튜닝이론 - 테이블 파티셔닝을 통한 DML 성능향상 (RANGE 파티션, HASH 파티션, LIST 파티션 (0) | 2024.02.07 |
| SQL 튜닝이론 - DirectPath I/O 를 활용한 DML 성능개선(DIRECT PATH I/O, 병렬 DML, APPEND, EXCLUSIVE MODE TX LOCK) (0) | 2024.02.06 |