Hãy xem xét các truy vấn sau đây hủy bỏ một số ít các tổng hợp vô hướng:
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);
Trên SQL Server 2017, tôi nhận được một kế hoạch với hai nhánh song song. Nhánh song song bên trái cảm thấy không phù hợp với tôi. Trình tối ưu hóa đảm bảo rằng sẽ chỉ có một đầu ra hàng duy nhất từ tổng hợp vô hướng toàn cầu, nhưng toán tử mẹ của nó là Luồng phân phối với phân vùng vòng tròn:
Khi tôi thực hiện truy vấn, tất cả các hàng sẽ chuyển đến một chuỗi như mong đợi. Không có vấn đề về hiệu năng với truy vấn này, nhưng truy vấn dự trữ 8 luồng song song với MAXDOP được đặt thành 4. Một lần nữa, tôi cảm thấy rằng điều này không đúng. Cả hai nhánh song song không thể thực thi cùng một lúc. Tôi muốn tránh việc đặt trước luồng công nhân không cần thiết vì tôi đã bật TF 2467 để thay đổi thuật toán lập lịch để xem xét số lượng luồng công nhân trên mỗi trình lập lịch.
Có thể viết lại truy vấn để có chính xác một nhánh song song có chứa quét bảng và tổng hợp cục bộ không? Ví dụ, tôi sẽ ổn với hình dạng chung bên dưới ngoại trừ việc tôi muốn vòng lặp lồng nhau thực thi trong một vùng nối tiếp:
Đối với Lý do ứng dụng ™ Tôi đặc biệt thích tránh chia tách truy vấn này thành nhiều phần. Nếu muốn, bạn có thể xem kế hoạch truy vấn thực tế ở đây . Nếu bạn muốn chơi cùng ở nhà, đây là T-SQL để tạo bảng được sử dụng trong truy vấn:
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;