Considere a seguinte consulta que desassocia alguns punhados de agregados escalares:
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);
No SQL Server 2017, recebo um plano com duas ramificações paralelas. O ramo paralelo esquerdo parece deslocado para mim. O otimizador tem garantia de que haverá apenas uma saída de linha do agregado escalar global, mas o operador pai dele é um Distribute Streams com particionamento round robin:
Quando executo a consulta, todas as linhas vão para um único thread conforme o esperado. Não há problema de desempenho com essa consulta, mas a consulta reserva 8 threads paralelos com MAXDOP definido como 4. Novamente, acho que isso está fora do lugar. É impossível que ambas as ramificações paralelas sejam executadas ao mesmo tempo. Desejo evitar reservas desnecessárias de threads de trabalho porque tenho o TF 2467 ativado, o que altera o algoritmo de agendamento para analisar o número de threads de trabalho por agendador.
É possível reescrever a consulta para ter exatamente uma ramificação paralela que contém a verificação da tabela e o agregado local? Por exemplo, eu ficaria bem com a forma geral abaixo, exceto que eu quero que o loop aninhado seja executado em uma zona serial:
Por motivos de aplicação ™, prefiro evitar dividir esta consulta em partes. Se desejar, você pode visualizar o plano de consulta real aqui . Se você quiser jogar em casa, aqui está o T-SQL para criar a tabela usada na consulta:
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;
fonte