본문 바로가기
Develop/MSSQL

SPOOL 연산자 성능 개선 - 2

by 3-stack 2022. 11. 24.

1. 사전구성

SELECT a.number num
  , CHAR(LEFT(b.high, 1) + 64) txt
  , LEFT(a.low, 1) group_id
INTO TB_FSpool03 
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
;
CREATE INDEX NIDX01_FSpool03 ON TB_FSpool03 (group_id) INCLUDE (num, txt);

 

table_name index_name index_description Is_Unique indexed_columns included_columns
TB_FSpool03 NIDX01_FSpool03 nonclustered 0 group_id num, txt

 

All density Average Length Columns
0.1111111119 1 group_id

 

RANGE_HI_KEY RANGE_HI_KEY EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
1 0 3,600 0 1
2 0 800 0 1
3 0 800 0 1
4 0 800 0 1
5 0 800 0 1
6 0 800 0 1
7 0 800 0 1
8 0 800 0 1
9 0 800 0 1

 

2. AS-IS

SELECT COUNT(DISTINCT num) num_cnt
  , COUNT(DISTINCT txt) txt_cnt 
FROM TB_FSpool03
WHERE group_id = '7';
  • 각 컬럼 별로 중복 제거된 행을 추출하기 위해선 컬럼마다 데이터를 새로 읽어내야 한다.
    이를 위해서 조건절로 탐색된 8천 건의 데이터를 임시 테이블로 저장한다.
    이를 재사용하면서 결과값을 추출한다.
  • 중간 결과 집합 전체를 임시 테이블로 저장하고 재사용하기 위해서 Table Spool (Eager Spool)이 사용된다.
    수행하는 과정에서 임시 테이블에 대한 I/O 비용이 높게 발생한다.

 

3. TO_BE

SELECT num_cnt, txt_cnt
FROM 
  (SELECT COUNT(DISTINCT num) num_cnt
  FROM TB_FSpool03
  WHERE group_id = '7') a
  , (SELECT COUNT(DISTINCT txt) txt_cnt
  FROM TB_FSpool03
  WHERE group_id = '7') b
;
  • 두 컬럼에 대해 중복 값이 제거된 행을 추출하기 위해 인덱스로 탐색된 8천 건의 데이터를 임시 테이블로 저장하고,
    재사용하면서 많은 I/O가 사용되었다.
  • COUNT(DISTINCT num)와 COUNT(DISTINCT txt)의 값을 각각 조회하도록 구문을 분리하고,
    두 결과를 조인하도록 변경하면 임시 데이터를 만들고 사용하는 비용을 제거할 수 있기 때문에 I/O를 개선할 수 있다.

댓글