database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Q&A 41303 게시물 읽기
No. 41303
슈퍼 울트라 초대용량 테이블 빠르게 초기화하는 방법
작성자
김익서(rladlrtj)
작성일
2016-12-20 15:18
조회수
6,175
오라클 성능 고도화 원리와 해법 저자인 조시형 대표이사가 쓴 글이 있어서 공유하고자 퍼왔습니다.
 
작성자 : oraking(조시형)
출처 : http://cafe.naver.com/dbian
 
오라클 버전이 업그레이드될 때마다 상당히 많은 기능이 추가된다. 매일 오라클만 가지고 씨름하는 필자로서도 따라가기 버겁다. 알던 것을 유지하기도 어려운데, 계속 새로운 기능을 익혀야 하니 가끔 짜증도 난다. 열심히 공부하고 나서야 쓸모없는 기능임을 알게 되니까. 새로운 기능 중 상당수는 실제 사용되지 않거나 이점도 없이 엔진만 점점 더 무겁게 한다.
잘 사용되지 않거나 사용하더라도 이점이 별로 없는 기능 중 하나가 'Deferred Segment Creation'이라고 생각한다. 이는 말 그대로 세그먼트 생성 시점을 늦추는 기능이다. 즉, 테이블을 생성할 때 익스텐트를 하나도 할당하지 않는다. 기존에는 테이블을 만들면 적어도 하나의 익스텐트를 가진 세그먼트를 만들어 테이블과 연결했고, 따라서 테이블은 적어도 익스텐트 하나는 가져야만 했다. 그런데 이제 익스텐트를 하나도 갖지 않는 테이블을 만드는 것이 가능해졌다. 11g에 추가된 기능이다.
이 기능은 사실 꼭 필요하진 않다. 어차피 테이블은 데이터를 입력하려고 만든다. 언제고 데이터를 입력할 텐데, 그때까지 익스텐트 할당을 미루는 게 무슨 이점이 있겠는가. 파티션 테이블에서 미래 파티션을 미리 만드는 경우 약간의 이점이 있긴 하다. 입력할 파티션이 없어 insert가 실패함으로 인해 생기는 운영 장애를 최소화하기 위해 파티션을 미리 만들어 두는 DBA들이 있는데, 그럴 때 공간 낭비를 막고 불필요한 파티션 액세스를 막는 정도의 효과가 있다. 그런데 그 효과가 크지 않고 파티션 테이블에는 반드시 maxvalue 파티션을 둔다는 운영원칙을 잘 지키면 미래 파티션을 미리 생성하지 않아도 되므로 오라클 입장에서 그런 이유로 Deferred Segment Creation 기능을 만들었다고 보기는 어렵다.
꼭 필요하지도 않은 기능을 오라클이 왜 만들었을까? 그 이유를 오늘에서야 깨달았다. 그것도 점심식사 도중 우연히 생각해 냈다. 지금부터 하는 얘기는 순전히 소설이다. 하지만, 상당히 신빙성 있는 얘기니 주의깊게 읽어보기 바란다.
 
테이블을 만들 때 최초 할당한 익스텐트에 세그먼트 헤더 블록이 위치한다. 세그먼트 헤더 블록에는 세그먼트와 관련한 정보들을 담는다. 대표적인 것이 익스텐트 맵, 즉 해당 세그먼트에 할당된 익스텐트 목록과 주소정보(데이터파일 내 위치)다. 익스텐트는 테이블(또는 인덱스)에 공간을 할당하는 단위다. 테이블 저장 공간이 부족할 때마다 익스텐트를 추가하고 해당 익스텐트 정보를 익스텐트 맵에 추가한다. 한번 할당된 익스텐트는 테이블을 Drop 하거나 Truncate 명령어로 초기화하지 않는 한 영원히 테이블에 연결된 상태로 남는다. 각 세그먼트에 이미 할당한 익스텐트 목록, 그리고 세그먼트에 아직 할당하지 않은 익스텐트 목록은 데이터파일 헤더에 비트맵으로 관리한다. (예전 DMT 방식에선 딕셔너리로 관리했다.)
 
테이블 Drop은 테이블과 세그먼트 간 연결고리를 끊고 딕셔너리에서 테이블과 세그먼트 정보를 삭제하는 방식이므로 아무리 큰 테이블도 순식간에 삭제한다. 테이블 정보를 유지한 상태에서 전체 데이터를 지우려면 Delete 또는 Truncate 문을 사용하는데, Delete 명령어를 사용하면 테이블 레코드를 일일이 지우고 인덱스 레코드도 한 건씩 찾아서 지우기 때문에 상당히 느리다. redo log까지 남겨야 하니 더 느리다.
테이블 정보를 유지한 상태에서 전체 데이터를 빠르게 지우려면 아래 Truncate문이 효과적이다. 익스텐트 맵을 저장하기 위해 최초 할당한 익스텐트를 제외한 모든 익스텐트를 반환하는 방식을 사용하므로 레코드 단위로 삭제하는 Delete와 비교할 수 없이 빠르다. redo log도 남기지 않으니 더 빠르다. drop storage 옵션은 생략해도 된다.
 
truncate table super_ultra_big_table drop storage;
 
데이터를 한 번에 지우되 할당된 익스텐트는 그대로 유지하려면 drop storage 대신 아래와 같이 reuse storage 옵션을 사용하면 된다. 이미 할당된 익스텐트를 반환하지 않고 HWM만 초기화하는 기능이다. 
 
truncate table super_ultra_big_table reuse storage;
 
문제는 Truncate 문을 사용하더라도 수만 개 익스텐트를 가진 초대용량 테이블을 지우는 데는 상당한 시간이 걸린다는 점이다. 테이블 세그먼트에 할당된 수만 개 익스텐트를 일일이 반환해 줘야 하기 때문이다. 이 때문에 DBA들이 종종 애를 먹곤 한다. Truncate 문에 버그가 있으니 쓰지 말라는 얘기도 그래서 생긴 듯하다. (물론 버전에 따라 실제로 버그가 있을 순 있다.)
Truncate도 익스텐트를 일일이 반환하지 않고 테이블 Drop처럼 세그먼트 정보를 통째로 삭제하는 방식을 사용하면 어떨까? 실제로 11gR2(11.2.0.2)에서 그 기능이 구현됐다. 예전에는 테이블 세그먼트당 최소 하나의 익스텐트를 남겨야 하므로 불가능했다면, 이제는 'Deferred Segment Creation' 기능 때문에 가능하다. 익스텐트를 하나도 갖지 않는 테이블 생성이 가능하므로 Truncate 할 때도 그 상태로 초기화하면 되는 것이다. 테이블을 Truncate 할 때 아래 옵션을 사용하면 제아무리 큰 초대용량 테이블도 순식간에 초기화된다. 
 
truncate table super_ultra_big_table drop ALL storage;
 
 
옵션 구문을 drop All storage보다 drop storage FASTLY 로 했으면 더 좋았겠다 싶다. 한정사 'ALL'은 이 기능의 본질이 마지막 익스텐트까지 남김 없이 지우는 데 있다고 생각하게 만들기 때문이다. 그래서  'Deferred Segment Creation'처럼 이 기능도 대수롭지 않게 여기게 한다. 마지막 남은 익스텐트까지 반환했다고 공간이 얼마나 더 절약되겠는가. 
그러다가 그 마지막 익스텐트마저 지울 수 있게 됨으로써 성능이 놀랍게 향상된 것을 발견하는 순간, 공간 절약보다 Truncate 속도를 향상시키는 데 목적이 있음을 깨닫게 된다. 큰 이점이 없는 'Deferred Segment Creation' 기능을 왜 도입했는지도 이해할 수 있게 된다. Truncate 성능을 향상시키려면 익스텐트가 전혀 없는 테이블 구조가 필요했던 것이다. 
 
다시 말하지만, Deferred Segment Creation 기능의 탄생배경은 소설에 불과한 얘기일 수 있다. 오라클 DBMS 개발자도 아닌데 그 기능을 왜 개발했는지 어찌 알겠는가. 하지만, 그럴듯하지 않은가? 믿거나 말거나지만 이렇게 스토리와 함께 기억하면 해당 기능을 더 효과적으로 사용하는 데 도움이 된다.
Deferred Segment Creation 기능의 탄생배경은 잊어도 좋지만, drop ALL storage 옵션은 잘 기억했다가 적절히 활용하기 바란다. 단, 익스텐트가 하나도 없는 상태가 되면 이후 어떤 문제가 생길 수 있는지는 잘 알고 써야 한다.
 
1. (주식시장 동시호가처럼) 순간적으로 많은 트랜잭션이 동시에 발생하면 익스텐트 할당으로 인해 심한 경합이 발생할 수 있다. 그럴 가능성이 있다면 테이블을 초기화한 후 익스텐트를 미리 할당해 두어야 한다.
2. Export 덤프 파일로 다른 DB에 Import 할 때 해당 테이블이 사라진다. 이후 발생한 Insert/Update/Delete는 모두 실패한다. Export 백업을 이용한다면, drop ALL storage 방식으로 테이블을 초기화한 후 익스텐트를 미리 할당해 두어야 한다.
 
지금까지 설명한 내용은 테이블 파티션을 Truncate 할 때도 적용된다. 오늘 소설은 여기까지.
 
끝.
[출처] 슈퍼 울트라 초대용량 테이블 빠르게 초기화하는 방법 (DBian 포럼) |작성자 oraking
[Top]
No.
제목
작성자
작성일
조회
41307db이중화 관련 db테이블 내 내용 수정 질문 드립니다 [1]
아르카
2017-01-07
5387
41306날짜형식 관련 질문드립니다. [3]
서범석
2017-01-06
5740
41305* UPDATE시 어떤게 속도가 빠른지 잘 몰라서 질문드립니다. [3]
소프
2016-12-27
5969
41303슈퍼 울트라 초대용량 테이블 빠르게 초기화하는 방법
김익서
2016-12-20
6175
41302oracle 10g 윈도우용 가지고계신분!!
서범석
2016-12-19
5592
41301clob 컬럼에 insert 시 [문자열이 너무 깁니다.] 에러 발생합니다.
초보자
2016-12-15
6966
41300리눅스 오라클 설치 질문요 [2]
qazsew
2016-12-14
7983
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2023 DSN, All rights reserved.
작업시간: 0.049초, 이곳 서비스는
	PostgreSQL v16.1로 자료를 관리합니다