2

我正在尝试对大量手动“分区”表执行聚合。我可以使用以下样式的 T-SQL 来做到这一点。

SELECT A, B, C, COUNT(*)
FROM
(
    SELECT ...
UNION ALL
    SELECT ...
UNION ALL
    SELECT ...
-- and many more!
) X
GROUP BY A, B, C

我的问题/担心是 SQL Server 似乎同时启动了所有嵌套的 SELECT。我想知道是否有任何模式可以让嵌套的 SELECT 一个接一个地运行,以减少服务器上的资源争用。

想要(并且怀疑正在发生)是所有子选择都在并行运行,并且它们中的大多数都在缓冲它们的输出(虽然不知道如何证明这一点)。

到目前为止,我能想到的最好的方法是一个显式的临时表(或表值变量),它将每个独立的输出写入它,然后聚合它,但这会导致比实际更多的行被物化需要:我希望输出流入聚合过程,这实际上意味着不需要太多的中间存储。

(嵌套选择实际上是非常复杂的自连接,但经过精心设计以产生合并连接,因此最少的中间结果需要在内存中或分页。)

有谁知道实现这一目标的更好模式?

4

2 回答 2

1

我想这可以运行得更快。虽然不确定

SELECT A, B, C, sum(cnt)
FROM
(
    SELECT A, B, C, COUNT(*) cnt
    FROM ...
    GROUP BY A,B,C
  UNION ALL
    SELECT ...
    FROM ...
    GROUP BY A,B,C
  UNION ALL
    SELECT ...
    FROM ...
    GROUP BY A,B,C
  -- and many more!
) X
GROUP BY A, B, C
于 2013-10-23T08:10:00.270 回答
0

将@i-one 和@t-clausen.dk 放在一起+ MERGE 最终成为我的最佳答案:

SELECT A, B, C, COUNT(*) cnt
INTO #tmp
FROM ...
GROUP BY A,B,C

ALTER TABLE #tmp ADD CONSTRAINT pk_#tmp PRIMARY KEY CLUSTERED (A,B,C)

MERGE INTO #tmp X
USING
(
    SELECT A, B, C, COUNT(*) cnt
    FROM ...
    GROUP BY A,B,C
) I
ON X.A = I.A AND X.B=I.B AND X.C=I.C
WHEN MATCHED THEN UPDATE SET X.cnt= X.cnt + I.cnt
WHEN NOT MATCHED THEN INSERT (A, B, C, cnt)
    VALUES (I.A, I.B, I.C, I.cnt);

-- repeat for more 

SELECT * FROM #tmp

注意:这对我来说是最好。每个单独的 SELECT 中的高行数使得这种方法很有价值。你的旅费可能会改变。

我仍然认为 SQL Server 相当愚蠢,因为它似乎通过并行运行 UNION ALL 的每个部分并需要这样的解决方法来过度使用资源。那好吧...

于 2013-10-28T21:48:27.073 回答