web-dev-qa-db-fra.com

Avertissement sur la mémoire "Subvention excessive" dans le plan de requête - comment savoir ce qui en est la cause?

J'exécute une requête qui donne l'avertissement d'une mémoire Excessive Grant.

Il y a trop de tables et d'index utilisés, y compris un view complexe, et il est donc difficile d'ajouter toutes les définitions ici.

J'essaie de trouver ce qui pourrait me causer le Excessive Grant. Peut-il s'agir de conversions?

En regardant le plan d'exécution, je peux voir ce qui suit:

<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>

Et celui-là:

<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>

Voici la requête, bien que vous puissiez voir la requête avec le plan d'exécution ici aussi :

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)
)

Voici à quoi ressemble l'avertissement:

Enter image description here

Le plan d'exécution est ici .

Comment puis-je faire face à cet avertissement?

Comme je l'ai dit auparavant, je regardais les conversions. Y a-t-il quelque chose que je puisse rechercher dans le plan d'exécution qui indiquerait les causes possibles de cette subvention excessive?

Obs. J'ai dit qu'il y avait trop d'objets impliqués, cependant, je peux ajouter ici tout ce qui est requis sur demande si cela peut aider à résoudre ce problème. Aucun problème.

9
Marcello Miorelli

Les deux types d'opérateurs les plus courants qui consomment de la mémoire sont:

  • Tris
  • Hashs

Si un plan est parallèle, les besoins en mémoire augmenteront pour compenser les échanges de threads à traverser les lignes. Les plans parallèles ne nécessitent pas l'intégralité de l'allocation de mémoire série * DOP (bien qu'il puisse exister une relation entre la mémoire série requise et DOP). La subvention complète est divisée et (espérons-le) utilisée uniformément sur tous les threads du plan.

Dans certains cas, Nested Loops Join peut également demander de la mémoire.

Les allocations de mémoire sont calculées par l'optimiseur en fonction du nombre de lignes et de la taille des données qui passeront par les opérateurs consommant de la mémoire. Comme ci-dessus, si le plan est parallèle, il peut demander plus. Un autre facteur est que les opérateurs consommateurs de mémoire peuvent partager la mémoire.

Par exemple, une partie de la mémoire consommée par un tri peut être transmise aux opérateurs en amont après le tri des données, et les hachages peuvent passer la mémoire en amont une fois la phase de construction initiale terminée, et les lignes sondées commencent à se déplacer en amont. Cela peut être observé via les informations sur les fractions de mémoire.

Dans votre plan, vous avez trois opérateurs de tri.

NUTS

Ce qui, combiné, l'optimiseur pense qu'il aura besoin de 2 Mo de mémoire pour fonctionner sans se répandre sur le disque. Il ne nécessite finalement que 24 Ko, d'où l'avertissement.

Les erreurs d'estimation des allocations de mémoire peuvent provenir de nombreux endroits. Dans votre requête, vous avez une seule variable: @arrivalDate.

Il n'est pas clair si ce paramètre se trouve dans une procédure stockée, ou si vous l'appelez localement. Dans les deux cas, vous pouvez essayer une astuce de recompilation pour voir si cela supprime l'avertissement en obtenant une estimation de cardinalité différente.

Si cela ne fonctionne pas, vous pouvez essayer d'ajuster les index afin que des opérations de tri distinctes ne soient pas nécessaires, mais cela peut être plus compliqué que cela ne vaut pour une si petite quantité de mémoire.

Pour référence:

11
Erik Darling