Considera la seguente query che non fa il pivot di alcune manciate di aggregati scalari:
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);
Su SQL Server 2017, ottengo un piano con due rami paralleli. Il ramo parallelo sinistro mi sembra fuori posto. L'ottimizzatore ha la garanzia che ci sarà un solo output di riga dall'aggregato scalare globale, ma l'operatore principale di esso è uno Stream di distribuzione con partizionamento round robin:
Quando eseguo la query, tutte le righe passano a un singolo thread come previsto. Non ci sono problemi di prestazioni con questa query, ma la query riserva 8 thread paralleli con MAXDOP impostato su 4. Ancora una volta, ritengo che sia fuori posto. È impossibile eseguire entrambi i rami paralleli contemporaneamente. Voglio evitare la prenotazione non necessaria del thread di lavoro perché ho abilitato TF 2467 che modifica l'algoritmo di pianificazione per esaminare il numero di thread di lavoro per programmatore.
È possibile riscrivere la query in modo che abbia esattamente un ramo parallelo che contiene la scansione della tabella e l'aggregazione locale? Ad esempio, starei bene con la forma generale di seguito, tranne per il fatto che voglio eseguire il ciclo nidificato in una zona seriale:
Per Application Reason ™ preferisco fortemente evitare di suddividere questa query in parti. Se lo si desidera, è possibile visualizzare il piano di query effettivo qui . Se desideri giocare a casa, ecco T-SQL per creare la tabella utilizzata nella query:
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;