Duplicate-weed는 MySQL 옵티마이저가 세미 조인(Semi-Join)을 처리할 때 사용하는 최적화 전략 중 하나입니다. IN 서브쿼리나 EXISTS 서브쿼리를 일반 조인으로 변환한 후, 발생할 수 있는 중복 레코드를 임시 테이블을 통해 제거합니다.
이름의 의미는 "duplicate(중복)"을 "weed out(제거한다)"는 뜻으로, 말 그대로 중복을 뽑아내는 전략입니다.
세미 조인(Semi-Join)이란 서브쿼리의 레코드가 존재하는지만 확인하고, 외부 테이블의 레코드는 한 번만 반환하는 조인 방식입니다.
-- 전형적인 세미 조인 쿼리
SELECT * FROM employees e
WHERE e.dept_id IN (
SELECT d.dept_id
FROM departments d
WHERE d.location = 'Seoul'
);
MySQL은 이런 서브쿼리를 내부적으로 조인으로 변환하여 처리하는데, 이때 서브쿼리 테이블에 중복 값이 있으면 외부 테이블의 같은 레코드가 여러 번 조인될 수 있습니다. 이를 방지하기 위한 여러 전략 중 하나가 Duplicate-weed입니다.
임시 테이블(Temporary Table)은 쿼리 실행 중에 중간 결과를 저장하기 위해 MySQL이 자동으로 생성하는 테이블입니다. Duplicate-weed는 이 임시 테이블에 유니크 인덱스를 만들어 중복을 자동으로 걸러냅니다.
왜 중복이 발생하나?
서브쿼리를 조인으로 변환할 때, 서브쿼리 테이블의 한 값에 여러 레코드가 매칭되면 외부 테이블의 레코드가 여러 번 반환됩니다.
-- departments 테이블
dept_id | location
--------|----------
10 | Seoul
10 | Seoul -- 중복!
20 | Busan
-- 조인 시 emp_id=1인 직원이 두 번 반환될 수 있음
Duplicate-weed의 동작 과정
실행 계획 확인
EXPLAIN 출력에서 Extra 컬럼에 Start temporary와 End temporary가 표시되면 Duplicate-weed 전략이 사용된 것입니다.
EXPLAIN SELECT * FROM employees e
WHERE e.dept_id IN (
SELECT d.dept_id FROM departments d
);
-- Extra: Start temporary; End temporary
언제 사용되나?
성능 특성
서브쿼리를 조인으로 변환하고, 임시 테이블의 유니크 인덱스를 통해 중복을 제거하는 과정입니다.