본문 바로가기
Develop/MSSQL

SPOOL 연산자 성능 개선 - 1

by 3-stack 2022. 11. 21.

1. 사전구성

SELECT a.number id
  , NEWID() txt
  , DATEADD(dd, a.number-1, '2020-01-01') date
INTO TB_FSpool02
FROM master..spt_values a, master..spt_values b
WHERE a.type = 'P'
  AND a.number BETWEEN 1 AND 10
  AND b.type = 'P'
  AND b.number BETWEEN 1 AND 5
;
CREATE CLUSTERED INDEX CIDX_FPool02 ON TB_FSpool02 (date);

SELECT ROW_NUMBER () OVER (ORDER BY a.number) id
  , CAST(LEFT(a.number*b.high, 2) AS INT) value
INTO TB_SSpool02
FROM master..spt_values a, master..spt_values b
WHERE a.type = 'P'
  AND a.number BETWEEN 1 AND 1000
  AND b.type = 'P'
  AND b.number BETWEEN 1 AND 1000
;
 
table_name index_name index_description Is_Unique indexed_columns included_columns
TB_FSpool02 CIDX_FPool02 clustered 0 date [NULL]

 

All density Average Length Columns
0.1000000015 8 date

 

RANGE_HI_KEY RANGE_ROW EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
2020-01-01 00:00:00.000 0 5 0 1
2020-01-03 00:00:00.000 5 5 1 5
2020-01-05 00:00:00.000 5 5 1 5
2020-01-07 00:00:00.000 5 5 1 5
2020-01-09 00:00:00.000 5 5 1 5
2020-01-10 00:00:00.000 0 5 0 1

 

2. AS-IS

SELECT f.id, f.txt
  , (SELECT s.value
    FROM TB_SSpool02 s
    WHERE f.id = s.id) value
FROM TB_FSpool02 f
WHERE date BETWEEN '2020-01-01' AND '2020-01-02'
;
  • [TB_FSpool02] 테이블에서 [date] 컬럼 범위 조건에 해당하는 [id] 값은 1 또는 2로 중복되어 있다.
  • 서브 쿼리에 동일한 값으로 반복되어 조인된다.
    조인하는 과정에서 서브 쿼리의 인덱스 부재로 인해 Index Spool (Lazy Spool)을 동반한 전체 스캔이 반복되면서 I/O가 높게 사용된다.
  • Index Spool (Lazy Spool)은 쿼리가 수행되는 동안에만 반복적으로 사용될 데이터를 임시 테이블에 저장한다.
    반복적으로 읽어야 하는 테이블을 매번 전체 스캔하는 대신 값이 전달될 때 조인된 결과를 Spool에 추가한다.
    동일한 값이 전달되면 기존에 생성한 Spool과 조인하면서 읽는 범위를 최소화 한다.
  • 이렇게 생성된 Spool에 내부적으로 비 클러스터형 인덱스를 생성하여 데이터를 재사용할 때 인덱스 탐색으로 수행한다.

 

3. TO_BE

CREATE INDEX NIDX01_SSpool02 ON TB_SSpool02 (id) INCLUDE (value);
  • Index Spool (Lazy Spool)은 데이터를 반복해서 읽어야 하는 구문에서 인덱스가 부재인 경우에 나타날 수 있다.
  • 필요한 데이터만 인덱스 탐핵할 수 있도록 후행 테이블인 [TB_SSpool02]의 조인 조건 컬럼에 인덱스를 생성하면 I/O를 감소시킬 수 있다.

댓글