본문 바로가기
Develop/MSSQL

내부 조인 스캔 범위 개선 (EXISTS)

by 3-stack 2022. 11. 17.

1. 사전 구성

SELECT *, CONVERT(INT, RIGHT(num,1)) AS code
INTO TB_DATA11
FROM 
  (SELECT ROW_NUMBER() OVER (ORDER BY A.number) AS num
    , LEFT(CONVERT(CHAR(8), DATEADD(HH, A.number, '2020-01-01'), 112), 6) AS date
  FROM master..spt_values A
    , (SELECT *
    FROM master..spt_values B
    WHERE type = 'P' AND number <= 500) B
  WHERE A.type = 'P'
) C
;
CREATE INDEX NIDX01_DATA11 ON TB_DATA11(code, date);
	
SELECT number AS id, number+2 AS code
INTO TB_CODE
FROM master..spt_values B
WHERE type = 'P' AND number BETWEEN 1 AND 10
;
CREATE INDEX NIDX01_CODE ON TB_CODE(code);

 

table_name index_name ndex_description Is_Unique indexed_columns included_columns
TB_CODE NIDX01_CODE nonclustered 0 code [NULL]
TB_DATA11 NIDX01_DATA11 nonclustered 0 code, date [NULL]

2. AS-IS

SELECT A.code
FROM TB_CODE A
INNER JOIN TB_DATA11 B
 ON A.code = B.code
 AND B.date > '20200101'
GROUP BY A.code
ORDER BY A.code
;
  • 최종 행 수가 7건 뿐임에도 [TB_DATA11] 테이블과 내부 조인이 수행되면서 약 45만건의 행을 읽고 이를 GROUP BY 절로 중복값을 제거하여 출력하게 된다.

3. TO-BE

SELECT tc.code 
FROM TB_CODE tc
WHERE EXISTS (
  SELECT 1 
  FROM TB_DATA11 td
  WHERE td.code = tc.code
    AND td.[date] > '20200101')
GROUP BY tc.code 
ORDER BY tc.code 
;
  • [TB_CODE] 테이블의 [code] 컬럼 값이 [TB_DATA11] 테이블에 존재하는지 여부만 확인하면 되기 때문에 EXISTS 절을 고려해 볼 수 있다.
  • EXISTS는 Semi Join으로 수행된다. 즉, 메인 쿼리 하나의 행에 대해서 서브 쿼리의 모든 행과 조인하지 않는다. 처음 조인에 성공하는 행을 만나면 스캔을 멈추고 해당 행을 최종 결과 셋에 포함한다.
  • EXISTS 절을 활용하면 후행 테이블의 스캔 범위를 감소시킬 수 있고, 선행 테이블에 대해서만 중복을 제거하면서 I/O를 개선할 수 있다.
 

'Develop > MSSQL' 카테고리의 다른 글

SPOOL 연산자 성능 개선 - 1  (0) 2022.11.21
IN 조건절 성능 이슈  (0) 2022.11.20
CROSS JOIN 반복 사용 테이블 통합  (0) 2022.11.16
CORSS APPLY 부분 범위 처리  (0) 2022.11.14
Show Me The Index 😁  (0) 2022.10.01

댓글