请考虑以下查询,该查询可取消少数几个标量聚合:
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:
当我执行查询时,所有行都按预期进入单个线程。该查询没有性能问题,但是该查询保留了8个并行线程,并将MAXDOP设置为4。同样,我觉得这不合适。两个并行分支不可能同时执行。我想避免不必要的工作线程预留,因为我启用了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;