メモリExcessive Grant
に関する警告を表示するクエリを実行しています。
複雑なview
を含め、使用されているテーブルとインデックスが多すぎるため、ここですべての定義を追加することは困難です。
Excessive Grant
の原因を突き止めようとしています。コンバージョンになるのでしょうか?
実行プランを見ると、次のことがわかります。
<ScalarOperator
ScalarString="CONVERT(date,[apia_repl_sub].[dbo].[repl_Aupair].[ArrivalDate] as [repl].[ArrivalDate],0)">
<Convert DataType="date" Style="0" Implicit="false">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[apia_repl_sub]" Schema="[dbo]" Table="[repl_Aupair]" Alias="[repl]" Column="ArrivalDate" />
</Identifier>
</ScalarOperator>
</Convert>
</ScalarOperator>
そしてこれは:
<ScalarOperator ScalarString="CONVERT(date,[JUNOCORE].[dbo].[applicationPlacementInfo].[arrivalDate] as [pi].[arrivalDate],0)">
<Convert DataType="date" Style="0" Implicit="false">
<ScalarOperator>
<Identifier>
<ColumnReference Database="[JUNOCORE]" Schema="[dbo]" Table="[applicationPlacementInfo]" Alias="[pi]" Column="arrivalDate" />
</Identifier>
</ScalarOperator>
</Convert>
</ScalarOperator>
これがクエリです 実行プランを含むクエリもここに表示されます :
DECLARE @arrivalDate DATEtime = '2018-08-20'
SELECT app.applicantID,
app.applicationID,
a.preferredName,
u.firstname,
u.lastname,
u.loginId AS emailAddress,
s.status AS statusDescription,
CAST(repl.arrivalDate AS DATE) AS arrivalDate,
app.moodleCourseComplete,
app.moodleCourseCompleteUpdated,
u.loginId,
c.countryName
FROM app.application AS app
JOIN app.applicant AS a ON a.applicantId = app.applicantId
JOIN usr.[user] AS u ON u.userId = a.userId
JOIN app.ref_applicationStatus AS s ON s.statusCode = app.status
JOIN APIA_Repl_Sub.dbo.repl_Aupair AS repl ON repl.JunoCore_applicationID = app.applicationID
JOIN app.Country AS c ON c.countryCode = a.nationalityCode
WHERE repl.arrivalDate = @arrivalDate
UNION ALL
(
SELECT app.applicantID,
app.applicationID,
app.preferredName,
app.firstname,
app.lastname,
app.emailAddress,
ap.status,
CAST(app.arrivalDate AS DATE) AS arrivalDate,
app.moodleCourseComplete,
app.moodleCourseCompleteUpdated,
app.emailAddress AS loginId,
c.countryName
FROM JUNOCore.dbo.vw_SelectApplication AS app
INNER JOIN JUNOCore.dbo.country c ON c.countryCode = app.nationalityCode
INNER JOIN JUNOCore.dbo.application as ap ON ap.applicationID = app.applicationID
WHERE arrivalDate = @arrivalDate AND
app.applicationID NOT IN (SELECT p4.applicationId FROM APCore.app.application p4)
)
警告は次のようになります。
実行計画はこちら 。
この警告にどのように対処しますか?
前に言ったように、コンバージョンを調べていました。この過剰な許可の考えられる原因を示す、実行計画で探すことができるものはありますか?
Obs。関連するオブジェクトが多すぎると言いましたが、この問題に対処するのに役立つ場合は、リクエストに応じて必要なものをここに追加できます。問題ない。
メモリを消費する最も一般的な2つのタイプの演算子は次のとおりです。
プランが並列の場合、メモリ要件は、スレッドが行を渡すための交換を補うためにいくらか増加します。パラレルプランでは、シリアルメモリ全体の許可* DOPは必要ありません(ただし、シリアルで必要なメモリとDOPの間に関係がある場合があります)。完全な付与は分割され、(うまくいけば)プラン内のすべてのスレッドで均等に使用されます。
場合によっては、 Nested Loops Join もメモリを要求することがあります。
メモリーの付与は、行数と、メモリーを消費するオペレーターを通過するデータのサイズに基づいて、オプティマイザーによって計算されます。上記のように、計画が並行している場合は、さらに要求される場合があります。別の要因は、メモリを消費するオペレーターがメモリを共有できることです。
たとえば、並べ替えによって消費されるメモリの一部は、データの並べ替え後に上流のオペレーターに渡すことができます。また、最初のビルドフェーズが完了し、プローブされた行が上流に移動し始めた後、ハッシュが上流のメモリを渡すことがあります。これは、メモリフラクション情報を介して確認できます。
計画には、3つのソート演算子があります。
これらを組み合わせると、オプティマイザは、ディスクに影響を与えずに実行するには2 MBのメモリが必要になると考えています。 24 KBしか必要としないため、警告が表示されます。
メモリ許可の誤った見積もりは、多くの場所から発生する可能性があります。クエリには、単一の変数があります:@arrivalDate
。
このパラメーターがストアドプロシージャ内にあるのか、ローカルで呼び出すのかは明確ではありません。どちらの場合でも、再コンパイルのヒントを試して、異なるカーディナリティの見積もりを取得することで警告が削除されるかどうかを確認できます。
それがうまくいかない場合は、個別のソート操作が不要になるようにインデックスを調整してみることをお勧めしますが、そのような少量のメモリの場合よりも複雑になる可能性があります。
参考のために:
パラメータスニッフィングのトラブルシューティングが正しい方法:パート1 (他のパートへのリンクは最初の投稿で提供されています)