테이블의 중복 문제는 SQL에서 가장 오래된 문제 중 하나이며, 특히 인터넷 서비스의 대량 성장과 대규모 데이터 마이그레이션으로 인해 더욱 심각해졌습니다. 초기에는 수동으로 문제를 해결했습니다: 중복을 찾기 위해 스크립트를 실행하고, 이를 제거했지만, 데이터 양이 증가함에 따라 이러한 접근 방식은 비효율적이었습니다.
문제: 부주의한 데이터 로딩, 마이그레이션 또는 오류로 인해 동일한 키 특성을 가진 수십 개의 행(예: 이메일 또는 여권)이 발생할 수 있습니다. 이는 통합 오류, 잘못된 분석 및 고객 신뢰 손실로 이어집니다.
해결책: 그룹화 및 윈도 함수 기능을 사용하여 중복에 대한 보고서를 작성하고, "올바른" 행 하나를 남기고 나머지 중복된 항목을 삭제하며, 키 필드에 대해 고유 제약 조건(UNIQUE)을 추가하고 정기적인 감사 절차를 의무화해야 합니다.
코드 예시:
WITH Duplicates AS ( SELECT email, COUNT(*) AS cnt FROM users GROUP BY email HAVING COUNT(*) > 1 ) SELECT u.* FROM users u JOIN Duplicates d ON u.email = d.email ORDER BY u.email, u.id;
중복 제거(최소 id를 가진 행 남기기):
DELETE FROM users WHERE id NOT IN ( SELECT MIN(id) FROM users GROUP BY email );
주요 특징:
DISTINCT를 사용하여 테이블에서 중복을 제거할 수 있습니까?
아니요, DISTINCT는 선택(SELECT)에서만 작동하며, 테이블에서 행을 삭제하지 않습니다. DELETE 또는 INSERT ... SELECT와 함께 DISTINCT를 사용하여 새 깨끗한 테이블을 생성해야 합니다.
DELETE ... WHERE id NOT IN (SELECT MIN(id) ...) 명령이 모든 중복을 보장되게 삭제합니까?
아니요, 키 열에 NULL이 있는 경우, 이러한 쿼리는 NULL 값 비교의 특성으로 인해 중복을 잘못 남길 수 있습니다.
더 이상 중복이 발생하지 않게 하려면 UNIQUE INDEX를 만드는 것으로 충분합니까?
아니요, 인덱스는 새로운 중복 삽입 시도만 보호하며, 이미 테이블에 존재하는 중복에는 영향을 미치지 않습니다.
CRM 시스템이 다양한 출처에서 사용자를 복사하며 이메일의 고유성을 고려하지 않아 50,000개의 중복이 생깁니다. UNIQUE 인덱스를 대량으로 추가하게 되면 시스템이 다운됩니다.
장점:
단점:
엔지니어가 전문 보고서를 통해 정기적으로 중복을 분석하고, 데이터베이스를 정리하며, 고유 인덱스를 생성합니다. 새로운 데이터를 마이그레이션하기 전에 유효성 검사를 실시합니다.
장점:
단점: