TRUNCATE — 테이블(또는 테이블 집합) 비우기
TRUNCATE — 테이블(또는 테이블 집합) 비우기
테이블의 모든 행을 순식간에 지워버리고 싶을 때 쓰는 명령이에요. DELETE가 행을 하나씩 검사하며 지우는 것과 달리 테이블을 실제로 스캔하지 않기 때문에 훨씬 빠르고, 디스크 공간도 즉시 회수해줘요.
출처: PostgreSQL 문서
본문
Synopsis
TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ]
[ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
설명 (Description)
TRUNCATE는 테이블 집합에서 모든 행을 신속하게 제거해요. 각 테이블에 대해 자격 없는(unqualified) DELETE를 수행한 것과 같은 효과를 가지지만, 실제로 테이블을 스캔하지 않기 때문에 더 빨라요. 게다가 이후의 VACUUM 작업을 요구하지 않고 즉시 디스크 공간을 회수해요. 이는 큰 테이블에서 가장 유용해요.
매개변수 (Parameters)
name
비우려는 테이블의 이름(선택적으로 스키마로 한정됨)이에요. 테이블 이름 앞에 ONLY가 지정되면 해당 테이블만 비워져요. ONLY가 지정되지 않으면 테이블과 모든 하위(descendant) 테이블(있다면)이 비워져요. 선택적으로 테이블 이름 뒤에 *를 지정해 하위 테이블이 포함됨을 명시적으로 나타낼 수 있어요.
RESTART IDENTITY
비워지는 테이블의 컬럼이 소유한 시퀀스(sequence)를 자동으로 재시작해요.
CONTINUE IDENTITY
시퀀스의 값을 변경하지 않아요. 이것이 기본값이에요.
CASCADE
이름이 지정된 테이블 중 하나에 외래 키 참조가 있는 모든 테이블, 또는 CASCADE로 인해 그룹에 추가된 테이블들을 자동으로 비워요.
RESTRICT
명령에 나열되지 않은 테이블에서 외래 키 참조가 있는 테이블이 있다면 비우기를 거부해요. 이것이 기본값이에요.
참고 (Notes)
테이블을 비우려면 그 테이블에 대한 TRUNCATE 권한이 있어야 해요.
TRUNCATE는 작동하는 각 테이블에 ACCESS EXCLUSIVE 잠금을 획득하는데, 이는 테이블에 대한 모든 동시 작업을 차단해요. RESTART IDENTITY가 지정되면 재시작될 시퀀스들도 마찬가지로 배타적으로 잠겨요. 테이블에 대한 동시 접근이 필요하다면 대신 DELETE 명령을 사용해야 해요.
TRUNCATE는 다른 테이블로부터 외래 키 참조가 있는 테이블에는 사용할 수 없어요. 단, 그러한 모든 테이블이 같은 명령에서 함께 비워지지 않는 한 말이에요. 그런 경우의 유효성 검사는 테이블 스캔을 요구할 텐데, 그게 바로 하지 않으려는 것이니까요. CASCADE 옵션을 사용하면 모든 종속 테이블을 자동으로 포함할 수 있어요. 하지만 이 옵션을 사용할 때는 아주 신중해야 해요. 의도하지 않은 데이터를 잃을 수도 있으니까요! 특히 비워지는 테이블이 파티션이라면 형제 파티션은 그대로 남지만, 캐스케이드는 구분 없이 모든 참조 테이블과 그 파티션들에 발생한다는 점에 유의해야 해요.
TRUNCATE는 테이블에 존재할 수 있는 ON DELETE 트리거는 발동시키지 않아요. 하지만 ON TRUNCATE 트리거는 발동시켜요. 어떤 테이블에 ON TRUNCATE 트리거가 정의되어 있다면, 모든 BEFORE TRUNCATE 트리거가 비우기가 일어나기 전에 발동되고, 모든 AFTER TRUNCATE 트리거는 마지막 비우기가 수행되고 시퀀스가 재설정된 후에 발동돼요. 트리거는 테이블이 처리되는 순서대로 발동돼요(먼저 명령에 나열된 테이블, 그다음 캐스케이딩으로 추가된 테이블).
TRUNCATE는 MVCC-safe하지 않아요. 비운 후에는, 비우기 전에 찍힌 스냅샷을 사용하는 동시 트랜잭션에게 테이블이 비어 있는 것으로 보일 거예요. 자세한 내용은 13.6절을 참고하면 돼요.
TRUNCATE는 테이블 내 데이터에 관해 트랜잭션-safe해요. 즉, 둘러싼 트랜잭션이 커밋되지 않으면 비우기는 안전하게 롤백돼요.
RESTART IDENTITY가 지정되면 암시된 ALTER SEQUENCE RESTART 작업도 트랜잭션적으로 수행돼요. 즉, 둘러싼 트랜잭션이 커밋되지 않으면 롤백돼요. 트랜잭션이 롤백되기 전에 재시작된 시퀀스에 추가 시퀀스 작업이 수행되면, 이 작업들이 시퀀스에 미친 효과는 롤백되지만 currval()에 미친 효과는 롤백되지 않는다는 점을 유의해야 해요. 즉, 트랜잭션 후 currval()은 실패한 트랜잭션 내부에서 얻은 마지막 시퀀스 값을 계속 반영하는데, 시퀀스 자체는 더 이상 그 값과 일치하지 않을 수 있어요. 이는 실패한 트랜잭션 이후의 currval()의 일반적인 동작과 비슷해요.
TRUNCATE는 외부 데이터 래퍼가 지원한다면 외부 테이블에도 사용할 수 있어요. 예를 들어 postgres_fdw를 참고하면 돼요.
예시 (Examples)
bigtable과 fattable 테이블을 비워요:
TRUNCATE bigtable, fattable;
동일하게 하되, 관련 시퀀스 생성기도 재설정해요:
TRUNCATE bigtable, fattable RESTART IDENTITY;
othertable 테이블을 비우고, 외래 키 제약을 통해 othertable을 참조하는 테이블로 캐스케이드해요:
TRUNCATE othertable CASCADE;
호환성 (Compatibility)
SQL:2008 표준에는 TRUNCATE TABLE tablename 구문의 TRUNCATE 명령이 포함되어 있어요. CONTINUE IDENTITY/RESTART IDENTITY 절도 그 표준에 등장하지만, 의미는 약간 다르면서 관련되어 있어요. 이 명령의 일부 동시성 동작은 표준에서 구현 정의로 남겨 두었기 때문에, 위의 참고 사항을 고려하고 필요하다면 다른 구현과 비교해 봐야 해요.
더 알아보기 (Learn more)
- 행을 조건에 따라 지우는
DELETE명령과 비교해 보면 좋아요. - 비운 뒤 남은 공간을 정리하는
VACUUM명령도 함께 참고하면 돼요. - 외래 키 참조에 대한 자세한 내용은
CREATE TABLE의 FOREIGN KEY 제약 조건을 참고하면 돼요.