Oracle/Oh Oracle

Delete vs ALTER TABLE ... MOVE INCLUDING ROWS WHERE 조건절 TABLESPACE.. UPDATE INDEXEX

darkturtle26 2023. 1. 20. 15:12

문서 보다가 일반 DELETE 와 ALTER TABLE MOVE UPDATE INDEXES 기능비교

 

 

비교 )

샘플이지만, CASE 1인 ALTER TABLE MOVE 의 경우, UNDO 발생이 없고, REDO 가 휠씬 적다

고려 휠씬 빠르게 수행 될것 같다.

상대적이겠지만, 삭제 량이 그렇게 많지 않다면 ALTER TABLE MOVE ( rollback 안됨 주의 !!!

삭제 량이 엄청 많다면,평소에 나눠서, LOOPING 식으로 야금야금 삭제..

 

-- CASE 1  ALTER TABLE ... MOVE INCLUDING ROWS WHERE 조건절 TABLESPACE.. UPDATE INDEXEX
ALTER TABLE T1 MOVE INCLUDING ROWS WHERE C1 <= 500000 TABLESPACE USERS UPDATE INDEXES;
--> WHERE 절에 만족하는 않는 ROW 는 삭제됨

--> TABLESPACE USERS 로  특정 TABLE 로 MOVE 가능

--> UPDATE INDEXES 옵션으로 관련 인덱스 VALID 유지 가능 ,  이 옵셥 빼고 MOVE 시, INVALID 상태로 변경됨 

 

-- CASE 2 일반적인DELETE 
DELETE T1 WHERE C1 <= 500000 ;

 

 

-- 1.  샘플 테이블 생성 
DROP TABLE T1 PURGE ;
CREATE TABLE T1 AS SELECT ROWNUM AS C1, SYSDATE - ROWNUM AS C2  FROM XMLTABLE('1 to 1000000');

ALTER TABLE T1 ADD CONSTRAINT T1_PK PRIMARY KEY ( C1 ) ;

-- 삭제 점 테이블 / 인덱스 사이즈 체크 
SELECT SEGMENT_NAME, BYTES/1024/1024 AS SIZE_MB, BLOCKS  FROM DBA_SEGMENTS WHERE SEGMENT_NAME  IN ('T1','T1_PK') ;
--    T1_PK	17	2176
--    T1	20	2560

-- 인덱스 상태 체크 
SELECT INDEX_NAME, STATUS,NUM_ROWS FROM DBA_INDEXES WHERE INDEX_NAME ='T1_PK';
-- T1_PK	VALID	1000000

--  >>>>  테이블 생성 후, 신규 세션으로 테스트 진행 필요 <<<<

-- 샘플 SID 지정 
select distinct sid from v$mystat ;


-- UNDO 및 REDO 측정 하기 
-- Check Undo 
SELECT s.inst_id, s.sid, s.serial#, s.status, t.used_ublk, t.used_urec 
FROM gv$session s, gv$transaction t, gv$process p
WHERE s.taddr = t.addr
and s.inst_id = t.inst_id
and s.paddr= p.addr
and s.INST_ID =p.INST_ID
and s.sid  = :v_sid
ORDER BY t.used_ublk desc, t.used_urec desC ;

-- Check Redo 
select  ss.sid, 'redo size:'||ss.value,    s.program,    s.module
from  v$statname     sn,v$sesstat     ss,v$session s
where ss.statistic#=sn.statistic# 
and   sn.name='redo size' 
and   s.sid=ss.sid 
and   s.sid = :v_sid 
and   ss.value>0
order by  ss.value;


-- 조건에 해당하지 않은 데이터는 재배치되지 않고 제거된다. 
-- CASE 1 
ALTER TABLE T1 MOVE INCLUDING ROWS WHERE C1 <= 500000 TABLESPACE USERS UPDATE INDEXES;

-- CASE 2 
DELETE T1 WHERE C1 <= 500000 ;

-- Check Undo 
SELECT s.inst_id, s.sid, s.serial#, s.status, t.used_ublk, t.used_urec 
FROM gv$session s, gv$transaction t, gv$process p
WHERE s.taddr = t.addr
and s.inst_id = t.inst_id
and s.paddr= p.addr
and s.INST_ID =p.INST_ID
and s.sid  = :v_sid
ORDER BY t.used_ublk desc, t.used_urec desC ;
-- CASE 1 
-- DDL 이라 UNDO 발생 없음

-- CASE 2 
-- USED_UBLK 14282
-- USED_UREC 1000000

-- Check Redo 
select  ss.sid, 'redo size:'||ss.value,    s.program,    s.module
from  v$statname     sn,v$sesstat     ss,v$session s
where ss.statistic#=sn.statistic# 
and   sn.name='redo size' 
and   s.sid=ss.sid 
and   s.sid = :v_sid 
and   ss.value>0
order by  ss.value;
-- CASE 1 
--redo size:936   >> redo size:  19,100,536

-- CASE 2 ( alter table 비교 10배 이상 redo 발생 )
--redo size:936   >> redo size: 263,581,944



SELECT SEGMENT_NAME, BYTES/1024/1024 AS SIZE_MB, BLOCKS  
FROM DBA_SEGMENTS WHERE SEGMENT_NAME  IN ('T1','T1_PK') ;
-- 테스트 전 
--    T1_PK	17	2176
--    T1	20	2560
-- CASE 1 -- ALTER TABLE 결과로 TABLE/INDEX 모두 사이즈가 줄어듦
--    T1_PK	9	1152
--    T1	10	1280
-- CASE 2  -- DELETE 로, TABLE/INDEX 모두 사이즈 변경 없음 
--    T1_PK	17	2176
--    T1	20	2560

-- INDEX 상태 및 NUM_ROWS 체크 
SELECT INDEX_NAME, STATUS,NUM_ROWS FROM DBA_INDEXES WHERE INDEX_NAME ='T1_PK';
-- 테스트 전 
-- T1_PK	VALID	1000000

-- CASE 1 --> DDL 로 자동으로  통계정보 수집 되는것으로 보임 
-- T1_PK    VALID    500000

-- CASE 2 --> DML 이라 변경 없음 
-- VALID	1000000

-- 테스트 후, NUM_ROWS 
SELECT COUNT(*) AS C1 FROM T1 ;
-- CASE1,2 모두 동일
--  500000