Estou executando uma consulta que está dando o aviso sobre uma memória Excessive Grant
.
Há muitas tabelas e índices usados, incluindo um complexo view
e, portanto, é difícil adicionar todas as definições aqui.
Estou tentando encontrar o que pode estar causando o Excessive Grant
. Pode ser conversões?
Olhando para o plano de execução, posso ver o seguinte:
<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>
E este:
<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>
Aqui está a consulta, embora você possa ver a consulta com o plano de execução aqui também :
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)
)
É assim que o aviso se parece:
O plano de execução está aqui .
Como faço para lidar com esse aviso?
Como eu disse antes, eu estava analisando as conversões. Há algo que eu possa buscar no plano de execução que indique as possíveis causas dessa outorga excessiva?
Obs. Eu disse que há muitos objetos envolvidos, no entanto, posso adicionar aqui o que for necessário mediante solicitação, se puder ajudar a resolver esse problema. Sem problemas.
Os dois tipos mais comuns de operadores que consomem memória são:
Se um plano for paralelo, os requisitos de memória aumentarão um pouco para compensar as trocas de encadeamentos para passar as linhas. Os planos paralelos não requerem toda a concessão de memória serial * DOP (embora possa haver uma relação entre a memória serial necessária e o DOP). A concessão total é dividida e (espero) usada uniformemente em todos os segmentos do plano.
Em alguns casos, a junção de loops aninhados também pode solicitar memória.
As concessões de memória são calculadas pelo otimizador com base no número de linhas e no tamanho dos dados que passarão pelos operadores que consomem memória. Como acima, se o plano for paralelo, ele pode pedir mais. Outro fator é que os operadores que consomem memória podem compartilhar memória.
Por exemplo, parte da memória consumida por uma classificação pode ser passada para operadores upstream depois que os dados são classificados, e os hashes podem passar a memória upstream depois que a fase de construção inicial é concluída e as linhas investigadas começam a se mover para cima. Isso pode ser observado através das informações de Fração de Memória.
Em seu plano, você tem três operadores de classificação.
O que, combinado, o otimizador acha que precisará de 2 MB de memória para ser executado sem derramar no disco. Acaba precisando apenas de 24 KB, daí o aviso.
As estimativas incorretas de concessão de memória podem vir de muitos lugares. Em sua consulta, você tem uma única variável:
@arrivalDate
.Não está claro se esse parâmetro está dentro de um procedimento armazenado ou se você o está chamando localmente. Em ambos os casos, você pode tentar uma dica de recompilação para ver se isso remove o aviso obtendo uma estimativa de cardinalidade diferente.
Se isso não funcionar, você pode tentar ajustar os índices para que as operações de classificação separadas não sejam necessárias, mas isso pode ser mais complicado do que vale a pena para uma quantidade tão pequena de memória.
Para referência:
Por que você está ajustando os procedimentos armazenados de forma errada (o problema com variáveis locais)
Solucionando problemas de detecção de parâmetros da maneira certa: parte 1 (os links para outras partes são fornecidos na primeira postagem)
Mais um post sobre variáveis locais