Pertimbangkan kueri berikut yang membatalkan beberapa agregat skalar:
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);
Pada SQL Server 2017, saya mendapatkan paket dengan dua cabang paralel. Cabang paralel kiri terasa tidak pada tempatnya. Pengoptimal memiliki jaminan bahwa hanya akan ada satu baris output dari agregat skalar global, namun operator induknya adalah Aliran Mendistribusikan dengan partisi round robin:
Ketika saya menjalankan kueri, semua baris menuju ke utas tunggal seperti yang diharapkan. Tidak ada masalah kinerja dengan kueri ini, tetapi kueri cadangan 8 thread paralel dengan MAXDOP diatur ke 4. Sekali lagi, saya merasa bahwa ini tidak pada tempatnya. Mustahil bagi kedua cabang paralel untuk mengeksekusi pada saat yang sama. Saya ingin menghindari reservasi utas pekerja yang tidak perlu karena saya mengaktifkan TF 2467 yang mengubah algoritma penjadwalan untuk melihat jumlah utas pekerja per penjadwal.
Apakah mungkin untuk menulis ulang kueri agar memiliki persis satu cabang paralel yang berisi pemindaian tabel dan agregat lokal? Sebagai contoh, saya akan baik-baik saja dengan bentuk umum di bawah ini kecuali bahwa saya ingin loop bersarang dijalankan di zona serial:
Untuk Alasan Aplikasi ™, saya lebih suka menghindari membagi kueri ini menjadi beberapa bagian. Jika diinginkan, Anda dapat melihat paket permintaan aktual di sini . Jika Anda ingin bermain bersama di rumah, inilah T-SQL untuk membuat tabel yang digunakan dalam kueri:
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;