Sql-Server

查詢計劃中有關記憶體“過度授予”的警告 - 如何找出導致它的原因?

  • January 26, 2021

我正在執行一個查詢,它給出有關記憶體的警告Excessive Grant

使用的表和索引太多,包括一個 complex 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)
)

這是警告的樣子:

在此處輸入圖像描述

執行計劃在這裡

我該如何處理這個警告?

正如我之前所說,我正在研究轉換。我可以在執行計劃中尋找什麼可以表明這種過度授權的可能原因嗎?

觀察。我說涉及的對象太多,但是,如果可能有助於解決此問題,我可以根據要求在此處添加所需的任何內容。沒問題。

最常見的兩種消耗記憶體的運算符是:

  • 排序
  • 雜湊

如果計劃是並行的,記憶體需求將增加一些以補償執行緒通過行的交換。並行計劃不需要整個串列記憶體授予 * DOP(儘管串列所需記憶體和 DOP 之間可能存在關係)。全部授權被拆分並(希望)在計劃中的所有執行緒中均勻使用。

在某些情況下,嵌套循環連接也可能會要求記憶體。

記憶體授予由優化器根據行數和將通過記憶體消耗運算符的數據大小來計算。如上所述,如果計劃是平行的,它可能會要求更多。另一個因素是消耗記憶體的運算元可以共享記憶體。

例如,排序消耗的一些記憶體可以在數據排序後傳遞給上游操作符,而雜湊可能會在初始建構階段完成後將記憶體傳遞給上游,並且探測的行開始向上游移動。這可以通過記憶體分數資訊觀察到。

在您的計劃中,您有三個排序運算符。

堅果

綜合起來,優化器認為它需要 2 MB 的記憶體才能執行而不會溢出到磁碟。它最終只需要 24 KB,因此發出警告。

記憶體授予錯誤估計可能來自許多地方。在您的查詢中,您有一個變數:@arrivalDate.

目前尚不清楚此參數是否在儲存過程中,或者您是否在本地呼叫它。在任何一種情況下,您都可以嘗試重新編譯提示,以查看是否通過獲取不同的基數估計來消除警告。

如果這不起作用,您可能想要嘗試調整索引,以便不需要單獨的排序操作,但這可能比如此少量的記憶體更複雜。

以供參考:

引用自:https://dba.stackexchange.com/questions/216931