回答:
追加のメモリを必要とするSQL Serverクエリの場合、許可はシリアルプランに対して導出されます。並列プランを探索して選択すると、メモリはスレッド間で均等に分割されます。
メモリ許可の見積もりは、以下に基づいています。
並列プランが選択された場合、並列交換(分散、再配布、およびストリームの収集)を処理するためのメモリオーバーヘッドがいくつかありますが、それらのメモリニーズは同じ方法で計算されません。
メモリを要求する最も一般的な演算子は次のとおりです。
メモリを必要とするあまり一般的でない演算子は、列ストアインデックスへの挿入です。これらはまた、メモリ許可が現在それらのDOPによって乗算されるという点でも異なります。
ソートのメモリ必要量は通常、ハッシュの場合よりもはるかに高くなります。並べ替えでは、すべての結果列を順序付け要素で並べ替える必要があるため、少なくともメモリ許可のデータの推定サイズを要求します。ハッシュは、選択されたすべての列を含まないハッシュテーブルを作成するためのメモリを必要とします。
このクエリを実行すると、意図的にDOP 1が示唆され、166 MBのメモリが必要になります。
SELECT *
FROM
(
SELECT TOP (1000)
u.Id
FROM dbo.Users AS u
ORDER BY u.Reputation
) AS u
OPTION(MAXDOP 1);
このクエリ(ここでもDOP 1)を実行すると、計画が変更され、メモリの付与がわずかに増えます。
SELECT *
FROM (
SELECT TOP (1000)
u.Id
FROM dbo.Users AS u
ORDER BY u.Reputation
) AS u
JOIN (
SELECT TOP (1000)
u.Id
FROM dbo.Users AS u
ORDER BY u.Reputation
) AS u2
ON u.Id = u2.Id
OPTION(MAXDOP 1);
2つのソートがあり、現在はハッシュ結合です。メモリ許可はハッシュビルドに対応するために少し増加しますが、並べ替え演算子を同時に実行できないため、倍増しません。
ネストされたループ結合を強制するようにクエリを変更すると、同時ソートを処理するために許可が2倍になります。
SELECT *
FROM (
SELECT TOP (1000)
u.Id
FROM dbo.Users AS u
ORDER BY u.Reputation
) AS u
INNER LOOP JOIN ( --Force the loop join
SELECT TOP (1000)
u.Id
FROM dbo.Users AS u
ORDER BY u.Reputation
) AS u2
ON u.Id = u2.Id
OPTION(MAXDOP 1);
ネストされたループはブロッキング演算子ではなく、ハッシュ結合はそうなので、メモリの付与は2倍になります。
このクエリは、さまざまな組み合わせの文字列データを選択します。選択する列に応じて、メモリ許可のサイズが増加します。
可変文字列データのデータサイズの計算方法は、行数*列の宣言された長さの50%です。これはVARCHARとNVARCHARに当てはまりますが、NVARCHAR列は2バイト文字を格納するため2倍になります。これは新しいCEで一部のケースで変更されますが、詳細は文書化されていません。
データのサイズもハッシュ操作にとって重要ですが、ソートの場合ほどではありません。
SELECT *
FROM
(
SELECT TOP (1000)
u.Id -- 166MB (INT)
, u.DisplayName -- 300MB (NVARCHAR 40)
, u.WebsiteUrl -- 900MB (NVARCHAR 200)
, u.Location -- 1.2GB (NVARCHAR 100)
, u.AboutMe -- 9GB (NVARCHAR MAX)
FROM dbo.Users AS u
ORDER BY u.Reputation
) AS u
OPTION(MAXDOP 1);
このクエリを別のDOPで実行すると、メモリ許可にDOPが乗算されません。
SELECT *
FROM (
SELECT TOP (1000)
u.Id
FROM dbo.Users AS u
ORDER BY u.Reputation
) AS u
INNER HASH JOIN (
SELECT TOP (1000)
u.Id
FROM dbo.Users AS u
ORDER BY u.Reputation
) AS u2
ON u.Id = u2.Id
ORDER BY u.Id, u2.Id -- Add an ORDER BY
OPTION(MAXDOP ?);
Exchangeオペレーターごとに並列バッファーを処理するためのわずかな増加があり、おそらくソートとハッシュのビルドがより高いDOPを処理するために追加のメモリを必要とするという内部的な理由があるかもしれませんが、それは明らかに乗算係数ではありません。