DB

[MySQL] DELETE + LIMIT / ORDER BY로 원하는 개수만 안전하게 삭제하는 방법

인생아 2025. 7. 2. 14:46
반응형

MySQL에서 데이터를 삭제할 때 모든 데이터를 한꺼번에 지우는 것이 아닌, 일부 데이터만 순차적으로 삭제하고 싶을 때가 많다.
예를 들어 오래된 로그를 100개씩 주기적으로 삭제하거나, 특정 정렬 기준에 따라 상위 몇 개만 삭제하고 싶을 수 있다.
이럴 때 사용하는 기능이 바로 DELETE + LIMIT / ORDER BY이다.

✅ DELETE + LIMIT 기본 구조

MySQL에서는 DELETE 문에 LIMIT 절을 붙여서 삭제할 행의 수를 제한할 수 있다.

DELETE FROM 테이블명
LIMIT 개수;

단순히 개수를 지정하면 랜덤하게 삭제되는 것이 아니라, MySQL 내부 스토리지 순서에 따라 처리된다.
만약 정렬 기준을 명확하게 설정하려면 ORDER BY를 함께 사용해야 한다.

✅ DELETE + ORDER BY + LIMIT 예제

DELETE FROM logs
ORDER BY created_at ASC
LIMIT 100;

이 쿼리는 가장 오래된 로그부터 100개만 삭제한다.
로그 정리, 대용량 테이블 슬라이딩 삭제, 배치 프로세스 최적화에 자주 활용되는 방식이다.

반응형

✅ ORDER BY로 정렬 기준 지정하기

DELETE FROM notifications
ORDER BY priority DESC, created_at ASC
LIMIT 50;

우선순위가 가장 높은 알림부터 생성일 오름차순으로 정렬하여 50개 삭제한다.
ORDER BY는 LIMIT과 함께 사용할 때만 의미가 있다.

✅ 서브쿼리로 동일한 DELETE 처리하기

MySQL은 8.0 이전 버전에서는 ORDER BY + LIMIT 조합이 문제를 일으킬 수 있었기 때문에, 아래처럼 서브쿼리를 사용하는 것도 유효한 방법이다.

DELETE FROM logs
WHERE id IN (
  SELECT id FROM logs ORDER BY created_at ASC LIMIT 100
);

이는 id 값을 기준으로 삭제 대상을 정확히 지정한 뒤 제거하는 방식으로, 더 안전하게 쿼리를 실행할 수 있다.

✅ LIMIT 사용 시 고려할 사항

  • 트랜잭션 처리가 필요한 경우, START TRANSACTION을 활용하여 여러 번 반복적으로 처리할 수 있다
  • ORDER BY 없이 LIMIT만 사용하는 것은 정렬 기준이 불명확하므로 예측 불가능한 삭제가 될 수 있다
  • 자동화 배치 작업에서 주기적으로 실행되도록 설정하면 성능 저하를 막고 데이터 정리를 효율적으로 수행할 수 있다
반응형

✅ LIMIT + OFFSET도 사용 가능

DELETE FROM logs
ORDER BY created_at ASC
LIMIT 10 OFFSET 100;

100번째 이후의 로그 중 10개를 삭제하는 방식이다. 페이징된 삭제 작업에 유용하다.

✅ 실무에서의 사용 사례

  1. 로그 정리: 매일 자정마다 오래된 로그 100개 삭제
  2. 스팸 댓글 제거: 최신순으로 정렬하여 스팸 태그 댓글 30개 삭제
  3. 데이터 마이그레이션 테스트: 제한된 수의 데이터를 테스트 삭제

✅ DELETE + LIMIT을 반복적으로 사용하는 방법

아래는 1,000개씩 데이터를 반복적으로 삭제하는 방법이다.

WHILE (1) DO
  DELETE FROM massive_table ORDER BY id ASC LIMIT 1000;
  IF ROW_COUNT() = 0 THEN
    LEAVE;
  END IF;
END WHILE;

이 방식은 프로시저나 반복 루프가 가능한 클라이언트 환경에서 대용량 테이블 삭제에 매우 유용하다.

✅ ORDER BY 없는 LIMIT 사용은 피해야 할까?

필요한 경우도 있지만, 삭제 순서가 중요하다면 반드시 ORDER BY와 함께 사용해야 한다.
예를 들어 created_at 순으로 오래된 데이터부터 정리하는 경우, ORDER BY가 없으면 의미 없는 삭제가 될 수 있다.

✅ 공식 문서 참고 링크

반응형