실무를 진행하다 보면 생각보다 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 |