본문 바로가기

DB

(MySQL) DELETE와 TRUNCATE

실무를 진행하다 보면 생각보다 delete와 truncate 명령어를 사용할 일이 그렇게 많지 않다. 그래서 종종 테이블의 모든 데이터를 지워야 하는 상황이 오면 delete 명령어를 사용할 지 truncate 명령어를 사용할 지 고민되는 경우가 있다. 아래에서는 두 가지 명령어의 동작 방식, 제약 조건, 성능 차이 등을 비교해보고, 실제 실무에서는 어떤 상황에서 어떤 명령어를 선택하는 게 더 적절한지에 대해 정리해보려 한다.

 


 

1. DELETE 명령어

 

DELETE는 DML(Data Manipulation Language) 명령어로 특정 조건에 맞는 행(row)을 삭제하거나 조건 없이 실행할 경우 테이블의 모든 행을 삭제할 수 있다.

  • WHERE 절을 사용해 원하는 행만 삭제 가능
  • 트랜잭션 내에서 실행하면 롤백(undo) 가능
  • ON DELETE 트리거가 있다면, 해당 트리거가 실행됨
  • 삭제 후에는 인덱스 데이터가 정리되지 않아, 필요시 OPTIMIZE TABLE 명령어로 재정비해야 할 수 있음
  • DML 명령어이므로 트랜잭션 내에서 실행 가능하며, 적절한 row 수준의 lock을 획득한 후 실행됨

 


 

2. TRUNCATE 명령어

 

TRUNCATE는 DDL(Data Definition Language) 명령어에 속하며 테이블의 모든 데이터를 빠르게 삭제하는 데 특화되어 있다.

  • 테이블을 드롭(drop)한 후 재생성(create) 하는 방식과 유사한 동작
  • 롤백 불가 (암묵적인 COMMIT 발생)
  • ON DELETE 트리거가 실행되지 않음
  • AUTO_INCREMENT 값이 초기화됨
  • 외래키 제약 조건이 걸린 테이블에는 사용 불가
  • DDL 명령어이므로 트랜잭션이 활성 상태이거나 테이블에 LOCK이 걸린 경우 실행 불가

 

3. DELETE 와 TRUNCATE 비교

 

항목 DELETE TRUNCATE
동작 방식 조건에 맞는 행(row)만 삭제 테이블 전체를 drop 후 재생성(내부적으로 빠른 데이터 삭제)
트랜잭션 롤백 가능 불가능
트리거 실행 ON DELETE 트리거가 실행됨 트리거가 실행되지 않음
성능 삭제할 행 수가 많으면 느림 전체 삭제 시 훨씬 빠름
외래키 제약 조건 외래키 관계에 따른 삭제 가능 외래키 관계가 있으면 실행 불가
인덱스 / AUTO_INCREMENT 인덱스 데이터 정리 X,
AUTO_INCREMENT 값 유지
인덱스 데이터 정리 O,
AUTO_INCREMENT 값 초기화

 


 

4. MySQL 버전에 따른 TRUNCATE 동작 방식 차이

 

MySQL 5.7 이하 버전

  • TRUNCATE는 내부적으로 데이터 페이지를 빠르게 해제하고 메타데이터(예: AUTO_INCREMENT 값)를 초기화하는 최적화된 방법으로 처리되었음.
  • 내부 구현 방식은 DROP TABLE + CREATE TABLE 명령어를 직접 호출하는 것이 아닌, 유사한 효과를 내는 최적화된 로직으로 처리됨.
  • , InnoDB 환경에서는 innodb_adaptive_hash_index 관련 이슈로 일시적 성능 저하가 발생할 수 있음.
innodb_adaptive_hash_index 이슈

- innodb_adaptive_hash_index는 InnoDB 스토리지 엔진에서 자주 조회되는 데이터 페이지에 대해 자동으로 해시 인덱스를 생성해, 읽기 성능을 개선하는 기능
- TRUNCATE 명령어가 실행되면서 InnoDB는 해당 테이블에 대한 adaptive hash index 항목들을 제거해야 하는데, 이 과정에서 LRU(Least Recently Used) 스캔이 발생하여 일시적으로 시스템 성능이 저하됨

* LRU 스캔: 가장 최근에 사용되지 않은 항목을 찾아내어 제거하는 과정

 

 

MySQL 8.0 이후 버전

  • TRUNCATE 명령어가 내부적으로 DROP TABLE과 CREATE TABLE 명령어를 호출하는 방식으로 리매핑(remapping)되어 동작함.
  • , 실제로 테이블을 drop하고 create하는 효과를 내지만, 사용자 입장에서는 단 한 줄의 명령어로 테이블 전체를 비울 수 있음.
  • 이 변경은 성능 및 일관성 측면에서 개선된 결과를 가져옴.

 


 

5. 실무에서 사용 시나리오

 

 

DELETE 사용 시

  • 조건부 삭제: 특정 조건(WHERE 절)을 만족하는 행만 삭제할 때
  • 롤백 필요: 트랜잭션 내에서 실행되어 삭제 작업을 취소할 가능성이 있을 때
  • 외래키가 존재하는 경우: 외래키 관계에 따른 삭제 처리가 필요한 경우

 

TRUNCATE 사용 시

  • 전체 데이터 삭제: 테이블의 모든 데이터를 빠르게 비워야 할 때
  • 퍼포먼스 중시: 대용량 테이블에서 삭제 속도가 중요한 경우
  • 테이블 재설정: AUTO_INCREMENT 값을 초기화하고, 테이블 상태를 깨끗하게 만들고자 할 때
주의사항

- 트랜잭션이 활성화되어 있거나, 테이블에 LOCK이 걸린 상황에서는 두 명령어 모두 제한이 있으므로, 사용 시점에 주의가 필요하다.
- 외래키 제약 조건이 있는 테이블에 TRUNCATE를 사용할 경우 오류가 발생하므로, 이러한 경우 DELETE를 사용하는 것이 바람직하다.

출처 :
https://dev.mysql.com/doc/refman/8.0/en/truncate-table.html
https://dev.mysql.com/doc/refman/8.0/en/delete.html

 

'DB' 카테고리의 다른 글

정규화(Normalization)  (2) 2024.10.07
DB Lock  (0) 2024.07.10
Transaction의 Isolation Level  (0) 2024.07.08
DB Transaction  (0) 2024.07.08
DB INDEX  (1) 2023.09.17