Lead 및 Lag 값을 얻기 위해 Join 및 Window 함수 사용 간의 성능 비교


11

나는 20M 행이있는 테이블이 있고, 각 행 3 열이 있습니다 time, id하고 value. 각각의 경우 idtime하는 존재 value상태에 대한. 특정 time에 대한 특정 리드 및 지연 값을 알고 싶습니다 id.

이것을 달성하기 위해 두 가지 방법을 사용했습니다. 한 가지 방법은 join을 사용하고 다른 방법은 clustered index on time및 창 함수 lead / lag를 사용하는 것 id입니다.

이 두 방법의 성능을 실행 시간별로 비교했습니다. 조인 방법은 16.3 초가 걸리고 윈도우 함수 방법은 20 초가 걸리며 인덱스 생성 시간은 포함되지 않습니다. 조인 방법이 무차별 적 인 동안 창 기능이 향상 된 것처럼 보였으므로 놀랐습니다.

다음은 두 가지 방법에 대한 코드입니다.

인덱스 생성

create clustered index id_time
 on tab1 (id,time)

가입 방법

select a1.id,a1.time
   a1.value as value, 
   b1.value as value_lag,
   c1.value as value_lead
into tab2
from tab1 a1
left join tab1 b1
on a1.id = b1.id
and a1.time-1= b1.time
left join tab1 c1
on a1.id = c1.id
and a1.time+1 = c1.time

다음을 사용하여 생성 된 IO 통계 SET STATISTICS TIME, IO ON:

결합 방법 통계

join 메소드 의 실행 계획은 다음과 같습니다.

창 기능 방법

select id, time, value, 
   lag(value,1) over(partition by id order by id,time) as value_lag,
   lead(value,1) over(partition by id order by id,time) as value_lead
into tab2
from tab1

(주문 만 time0.5 초 절약)

Window 함수 방식 의 실행 계획은 다음과 같습니다.

IO 통계

[윈도우 기능 방법 통계 4]


나는 데이터를 체크인했으며 sample_orig_month_1999원시 데이터는 id및에 의해 잘 정렬 된 것으로 보입니다 time. 이것이 성능 차이의 이유입니까?

join 메소드는 window 함수 메소드보다 더 많은 논리적 읽기를 가지고있는 반면, 전자의 실행 시간은 실제로는 적습니다. 전자가 더 나은 병렬 처리를 갖기 때문입니까?

간결한 코드로 인해 윈도우 함수 방법이 마음에 듭니다.이 특정 문제에 대해 속도를 높일 수있는 방법이 있습니까?

Windows 10 64 비트에서 SQL Server 2016을 사용하고 있습니다.

답변:


11

자체 조인에 비해 상대적으로 낮은 행 모드 성능 LEADLAG창 기능은 새로운 것이 아닙니다. 예를 들어 Michael Zilberstein 2012 년에 SQLblog.com에이 기사를 작성 했습니다. (반복 된) 세그먼트, 시퀀스 프로젝트, 창 스풀 및 스트림 집계 계획 연산자에는 약간의 오버 헤드가 있습니다.

계획 섹션

SQL Server 2016 에는 창 집계에 대해 배치 모드 처리 를 활성화하는 새로운 옵션 이 있습니다. 비어있는 경우에도 테이블에 일종의 columnstore 인덱스가 필요합니다. 최적화 프로그램이 배치 모드 계획을 고려하려면 현재 열 저장소 인덱스가 필요합니다. 특히 훨씬 효율적인 Window Aggregate 배치 모드 연산자를 사용할 수 있습니다.

이 경우를 테스트하려면 빈 비 클러스터형 columnstore 인덱스를 만듭니다.

 -- Empty CS index
CREATE NONCLUSTERED COLUMNSTORE INDEX dummy 
ON dbo.tab1 (id, [time], [value]) 
WHERE id < 0 AND id > 0;

쿼리 :

SELECT
    T1.id,
    T1.[time],
    T1.[value],
    value_lag = 
        LAG(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time]),
    value_lead =
        LEAD(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time])
FROM dbo.tab1 AS T1;

이제 다음과 같은 실행 계획을 제공해야합니다.

배치 모드 행 저장소 계획

... 훨씬 빨리 실행될 수 있습니다.

OPTION (MAXDOP 1)결과를 새 테이블에 저장할 때 동일한 계획 형태를 얻으려면 또는 다른 힌트 를 사용해야 할 수도 있습니다 . 계획의 병렬 버전에는 배치 모드 정렬 (또는 가능하면 2 개)이 필요합니다. 오히려 하드웨어에 따라 다릅니다.

배치 모드 창 집계 연산자에 대한 자세한 내용은 Itzik Ben-Gan의 다음 기사를 참조하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.