Dans SQL Server, comment le parallélisme modifie-t-il les allocations de mémoire?


9

J'ai entendu des choses contradictoires sur les allocations de mémoire pour les requêtes de sélection parallèles:

  • Les allocations de mémoire sont multipliées par le DOP
  • Les allocations de mémoire sont divisées par DOP

Lequel est-ce?

Réponses:


10

Souper?

Pour les requêtes SQL Server qui nécessitent de la mémoire supplémentaire, des autorisations sont dérivées pour les plans série. Si un plan parallèle est exploré et choisi, la mémoire sera divisée également entre les threads.

Les estimations des allocations de mémoire sont basées sur:

  • Nombre de lignes (cardinalité)
  • Taille des lignes (taille des données)
  • Nombre d'opérateurs simultanés consommant de la mémoire

Si un plan parallèle est choisi, il y a une surcharge de mémoire pour traiter les échanges parallèles (distribuer, redistribuer et rassembler des flux), mais leurs besoins en mémoire ne sont toujours pas calculés de la même manière.

Opérateurs consommateurs de mémoire

Les opérateurs les plus courants qui demandent de la mémoire sont

  • Tris
  • Hashs (jointures, agrégats)
  • Boucles imbriquées optimisées

Les opérateurs moins courants qui nécessitent de la mémoire sont des insertions dans les index de stockage de colonnes. Celles-ci diffèrent également en ce que les allocations de mémoire sont actuellement multipliées par DOP pour elles.

Les besoins en mémoire pour les tris sont généralement beaucoup plus élevés que pour les hachages. Les tris demanderont au moins la taille estimée des données pour une allocation de mémoire, car ils doivent trier toutes les colonnes de résultats en fonction des éléments de commande. Les hachages ont besoin de mémoire pour créer une table de hachage, qui n'inclut pas toutes les colonnes sélectionnées.

Exemples

Si j'exécute cette requête, suggérée intentionnellement par DOP 1, elle demandera 166 Mo de mémoire.

SELECT *
FROM 
     (  
        SELECT TOP (1000) 
               u.Id 
        FROM dbo.Users AS u
        ORDER BY u.Reputation
     ) AS u
OPTION(MAXDOP 1);

DES NOISETTES

Si j'exécute cette requête (encore une fois, DOP 1), le plan changera et l'allocation de mémoire augmentera légèrement.

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

DES NOISETTES

Il y a deux tris et maintenant un Hash Join. L'allocation de mémoire augmente un peu pour prendre en charge la génération de hachage, mais elle ne double pas car les opérateurs de tri ne peuvent pas s'exécuter simultanément.

Si je modifie la requête pour forcer une jointure de boucles imbriquées, la subvention doublera pour traiter les tris simultanés.

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

DES NOISETTES

L'allocation de mémoire double car la boucle imbriquée n'est pas un opérateur de blocage et la jointure par hachage l'est.

La taille des données est importante

Cette requête sélectionne des données de chaîne de différentes combinaisons. Selon les colonnes que je sélectionne, la taille de l'allocation de mémoire augmente.

La façon dont la taille des données est calculée pour les données de chaîne variable est les lignes * 50% de la longueur déclarée de la colonne. Cela est vrai pour VARCHAR et NVARCHAR, bien que les colonnes NVARCHAR soient doublées car elles stockent des caractères codés sur deux octets. Cela change dans certains cas avec le nouveau CE, mais les détails ne sont pas documentés.

La taille des données est également importante pour les opérations de hachage, mais pas au même degré que pour les tris.

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

Mais qu'en est-il du parallélisme?

Si j'exécute cette requête sur différents DOP, l'allocation de mémoire n'est pas multipliée par 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 ?);

DES NOISETTES

Il y a de légères augmentations pour gérer plus de tampons parallèles par opérateur d'échange, et il y a peut-être des raisons internes pour lesquelles les générations Sort et Hash nécessitent de la mémoire supplémentaire pour gérer un DOP plus élevé, mais ce n'est clairement pas un facteur multiplicateur.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.