소수의 스칼라 집계를 해제하는 다음 쿼리를 고려하십시오.
SELECT A, B
FROM (
SELECT
MAX(CASE WHEN ID = 1 THEN 1 ELSE 0 END) VAL1
, MAX(CASE WHEN ID = 2 THEN 1 ELSE 0 END) VAL2
, MAX(CASE WHEN ID = 3 THEN 1 ELSE 0 END) VAL3
, MAX(CASE WHEN ID = 4 THEN 1 ELSE 0 END) VAL4
, MAX(CASE WHEN ID = 5 THEN 1 ELSE 0 END) VAL5
, MAX(CASE WHEN ID = 6 THEN 1 ELSE 0 END) VAL6
, MAX(CASE WHEN ID = 7 THEN 1 ELSE 0 END) VAL7
, MAX(CASE WHEN ID = 16 THEN 1 ELSE 0 END) VAL16
FROM dbo.PARALLEL_ZONE_REPRO
) q
UNPIVOT(B FOR A IN (
VAL1
,VAL2
,VAL3
,VAL4
,VAL5
,VAL6
,VAL7
,VAL16
)) U
OPTION (MAXDOP 4);
SQL Server 2017에서는 두 개의 병렬 분기가있는 계획이 있습니다. 왼쪽 평행 가지가 제 위치에 있지 않습니다. 옵티마이 저는 글로벌 스칼라 집계에서 단일 행 출력 만 보장하지만 상위 연산자는 라운드 로빈 파티셔닝이있는 Distribute Streams입니다.
쿼리를 실행하면 모든 행이 예상대로 단일 스레드로 이동합니다. 이 쿼리에는 성능 문제가 없지만 MAXDOP가 4로 설정된 8 개의 병렬 스레드를 예약합니다. 다시 말하지만 이것이 잘못된 것 같습니다. 두 병렬 분기가 동시에 실행되는 것은 불가능합니다. 스케줄러 당 작업자 스레드 수를 확인하도록 스케줄링 알고리즘을 변경하는 TF 2467을 활성화했기 때문에 불필요한 작업자 스레드 예약을 피하고 싶습니다.
테이블 스캔과 로컬 집계를 포함하는 하나의 병렬 분기를 갖도록 쿼리를 다시 작성할 수 있습니까? 예를 들어 중첩 루프를 직렬 영역에서 실행하려는 것을 제외하고는 아래의 일반적인 모양이 좋습니다.
Application Reasons ™의 경우이 쿼리를 여러 부분으로 나누지 않는 것이 좋습니다. 원하는 경우 여기 에서 실제 쿼리 계획을 볼 수 있습니다 . 집에서 함께 놀고 싶다면 쿼리에 사용되는 테이블을 만드는 T-SQL이 있습니다.
DROP TABLE IF EXISTS dbo.PARALLEL_ZONE_REPRO;
CREATE TABLE dbo.PARALLEL_ZONE_REPRO (
ID BIGINT,
FILLER VARCHAR(100)
);
INSERT INTO dbo.PARALLEL_ZONE_REPRO WITH (TABLOCK)
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) % 15
, REPLICATE('Z', 100)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;