수백만 건, 수천만 건의 데이터를 삭제할 때 어떤 명령어를 사용하시나요? 단순히 "데이터를 지운다"는 결과는 같을지 몰라도, 그 내부에서 발생하는 일과 DB에 가해지는 부하는 천차만별입니다. 상황에 맞는 최적의 삭제 방식을 선택하기 위해 각 명령어의 특징을 파헤쳐 보겠습니다.
1. 명령어별 핵심 요약 및 비교
먼저 바쁜 분들을 위해 세 가지 방식의 차이점을 표로 정리했습니다.
| 구분 | DELETE | TRUNCATE | DROP |
| 명령어 성격 | DML (Data Manipulation) | DDL (Data Definition) | DDL (Data Definition) |
| 삭제 단위 | 행(Row) 단위 | 테이블 전체 (공간 초기화) | 테이블 자체를 삭제 |
| 로그 발생량 | 많음 (행당 로그 기록) | 적음 (페이지 단위 기록) | 거의 없음 |
| 속도 | 느림 | 빠름 | 가장 빠름 |
| Rollback | 가능 | 불가능 (자동 커밋) | 불가능 (자동 커밋) |
| 조건(WHERE) | 사용 가능 | 사용 불가능 | 사용 불가능 |
2. DELETE: 신중하고 섬세한 삭제
DELETE는 데이터 조작어(DML)입니다. 테이블의 틀은 그대로 두고 내부의 레코드를 하나씩 지우는 방식입니다.
- 동작 원리: 각 행을 삭제할 때마다 해당 데이터를 Undo 로그나 Redo 로그에 기록합니다. 이는 사용자가 실수했을 때 ROLLBACK을 하기 위함입니다.
- 리소스 부하: 만약 1,000만 건의 데이터를 DELETE하면, 1,000만 번의 로그 기록이 발생합니다. 이 과정에서 CPU와 I/O 사용량이 급증하며, 로그 파일(Transaction Log)이 가득 차서 DB가 중단될 수도 있습니다.
- HWM(High Water Mark): 데이터를 지워도 테이블이 차지하고 있던 물리적인 공간(High Water Mark)은 줄어들지 않습니다. 즉, 데이터를 다 지워도 테이블 크기는 그대로 유지됩니다.
3. TRUNCATE: 테이블 초기화 (공장 초기화)
TRUNCATE는 데이터 정의어(DDL)입니다. 테이블의 모든 데이터를 한 번에 비우고, 사용했던 저장 공간까지 반납합니다.
- 동작 원리: 행 단위로 지우는 것이 아니라, 테이블이 데이터를 담고 있던 데이터 페이지(Data Page) 자체를 해제해 버립니다.
- 로그 최소화: 삭제된 행 하나하나를 기록하지 않고, "어떤 페이지가 해제되었다"는 정도의 최소한의 로그만 남깁니다. 그래서 DELETE보다 수십 배 이상 빠릅니다.
- 공간 회수: 테이블의 용량이 다시 0에 가깝게 줄어듭니다. 새로 데이터를 넣으면 초기 상태부터 다시 쌓이게 됩니다.
4. DROP: 존재 자체를 삭제
DROP 역시 DDL이며, 데이터뿐만 아니라 테이블의 구조(스키마)와 정의 자체를 데이터 사전(Data Dictionary)에서 삭제합니다.
- 동작 원리: 테이블에 할당된 모든 공간을 즉시 해제하고, 해당 테이블과 관련된 인덱스, 제약 조건까지 모두 삭제합니다.
- 결과: 명령 실행 후에는 해당 테이블을 조회(SELECT)할 수조차 없습니다. 복구하려면 백업본을 가져와야만 합니다.
5. 실무에서의 상황별 선택 가이드
💡 특정 조건의 데이터만 지워야 할 때
고민할 것 없이 DELETE를 써야 합니다. 하지만 데이터가 너무 많다면 WHERE 절에 인덱스가 걸려 있는지 확인하고, Batch 단위(예: 1만 건씩 나누어서)로 삭제하는 것이 안전합니다.
💡 전체 데이터를 지우고 테이블 구조만 남길 때
로그 데이터 정리나 초기화가 목적이라면 TRUNCATE가 압도적으로 유리합니다. 하지만 FOREIGN KEY 제약 조건이 걸려 있는 경우 실행이 제한될 수 있으니 주의해야 합니다.
💡 테이블을 새로 만들어야 하거나 아예 안 쓸 때
망설임 없이 DROP을 사용하세요.
🏁 성능 최적화 팁: 대량 데이터 삭제 시 주의사항
- 트랜잭션 로그 관리: DELETE 실행 전, 로그 파일 용량이 충분한지 확인하세요.
- 인덱스 오버헤드: DELETE 시 해당 테이블에 인덱스가 많으면 각 행을 지울 때마다 인덱스 구조도 재배치해야 하므로 성능이 매우 떨어집니다. 대량 삭제 전에는 잠시 인덱스를 비활성화(Disable) 하는 것도 방법입니다.
- 테이블 재생성 전략 (CTAS): 수천만 건 중 일부(예: 10%)만 남기고 다 지워야 한다면, 차라리 남길 데이터만 새 테이블에 복사(CREATE TABLE AS SELECT)한 뒤 기존 테이블을 DROP하는 것이 훨씬 빠를 수 있습니다.
'TECH > sql' 카테고리의 다른 글
| 대용량 데이터의 적, OFFSET 페이징 탈출하기: No-Offset(커서 기반) 완벽 가이드 (1) | 2026.03.12 |
|---|---|
| [SQL] 피벗(Pivot) 테이블 완벽 가이드: Oracle, MySQL, PostgreSQL별 구현 패턴 (0) | 2026.03.06 |
| [SQL] 데이터 분석의 끝판왕: 윈도우 함수(Window Function) DBMS별 차이와 실무 활용 (0) | 2026.03.04 |
| [Oracle] 옵티마이저는 완벽하지 않다! SQL 힌트(Hint)로 실행 계획 제어하기 (0) | 2026.03.02 |
| [SQL 성능 최적화] EXISTS vs IN: 동작 원리부터 성능 차이까지 완벽 분석 (0) | 2026.03.01 |