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 を次々に実行できるパターンがあるかどうか疑問に思っています。

私が望んでいない(そして起こっていると思われる)のは、すべてのサブSELECTが並行して実行されており、それらのほとんどが出力をバッファリングしていることです(ただし、これを証明する方法はわかりません)。

これまでに思いついたのは、明示的な一時テーブル (またはテーブル値の変数) で、それぞれからの出力が独立して書き込まれ、それを集計しますが、実際よりも多くの行が具体化されます。である必要があります: 出力を集計プロセスにストリーミングすることを望みます。これは、中間ストレージがあまり必要ないことを効果的に意味します。

(ネストされた選択は実際には非常に複雑な自己結合ですが、マージ結合になるように細工されているため、最小限の中間結果をメモリまたはページングする必要があります。)

これを達成するためのより良いパターンを知っている人はいますか?

4

2 に答える 2

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 内の行数が多いため、このアプローチは価値がありました。あなたのマイレージは異なる場合があります。

UNION ALL の各部分を並行して実行し、このような回避策を要求することによって、リソースを過剰にコミットしているように見えるという点で、SQL Server はかなりばかげていると私はまだ考えています。しかたがない...

于 2013-10-28T21:48:27.073 に答える