1. 사전구성
SELECT c.id , CASE WHEN c.id <=5 THEN 1 WHEN c.id <= 10 THEN 2 WHEN c.id <= 15 THEN 3 WHEN c.id <= 20 THEN 4 ELSE 5 END gid , NEWID() code1 , NEWID() code2 INTO TB_Maind8 FROM (SELECT ROW_NUMBER() OVER(ORDER BY a.number) id FROM master..spt_values a, master..spt_values b WHERE a.type = 'P' AND a.number BETWEEN 1 AND 100 AND b.type = 'P' AND b.number BETWEEN 1 AND 100) c ; SELECT * INTO TB_Subd8 FROM TB_Maind8; CREATE CLUSTERED INDEX CIDX_Maind8 ON TB_Maind8(gid); CREATE INDEX IDX01_Subd8 ON TB_Subd8(id);
table_name | index_name | index_description | Is_Unique | indexed_columns | included_columns |
TB_Maind8 | CIDX_Maind8 | clustered | 0 | gid | [NULL] |
TB_Subd8 | IDX01_Subd8 | nonclustered | 0 | id | [NULL] |
2. AS-IS
SELECT COUNT(id) FROM TB_Subd8 a WHERE id NOT IN (SELECT DISTINCT id FROM TB_Maind8 WHERE gid BETWEEN 2 AND 4);
- 데이터를 제외하기 위해 NOT IN 절 사용.
- 두 테이블의 데이터를 비교하는 과정에서 NL Join이 수행.
- 선행 테이블 [TB_Subd8]의 결과 집합 10,000건에 대해 후행 테이블인 [TB_Maind8]에 반복 조인되면서 많은 I/O 비용 발생.
3. TO_BE
SELECT COUNT(a.id) FROM TB_Subd8 a LEFT JOIN ( SELECT id FROM TB_Maind8 WHERE gid BETWEEN 2 AND 4 ) b ON b.id = a.id WHERE b.id IS NULL ;
- LEFT OUTER JOIN으로 구문 변경하여 다른 조인 방식으로 수행되도록 유도.
- [TB_Subd8] 테이블은 조인 키에 해당되는 [id] 컬럼이 인덱스로 인해 이미 정렬.
- [TB_Maind8] 테이블은 DISTINCT로 정렬을 선행하기 때문에,
테이블을 한 번씩 읽어내면서 정렬된 데이터로 조인하는 Merge Join으로 성능 개선.
'Develop > MSSQL' 카테고리의 다른 글
SPOOL 연산자 성능 개선 - 3 (0) | 2022.11.30 |
---|---|
SPOOL 연산자 성능 개선 - 2 (0) | 2022.11.24 |
SPOOL 연산자 성능 개선 - 1 (0) | 2022.11.21 |
IN 조건절 성능 이슈 (0) | 2022.11.20 |
내부 조인 스캔 범위 개선 (EXISTS) (0) | 2022.11.17 |
댓글