In SQL Server, in che modo il parallelismo modifica le concessioni di memoria?


9

Ho sentito cose contrastanti sulle concessioni di memoria per query di selezione parallele:

  • Le concessioni di memoria vengono moltiplicate per DOP
  • Le assegnazioni di memoria vengono divise per DOP

Cos'è questo?

Risposte:


10

Sup?

Per le query di SQL Server che richiedono memoria aggiuntiva, le sovvenzioni vengono derivate per i piani seriali. Se viene esplorato e scelto un piano parallelo, la memoria verrà suddivisa equamente tra i thread.

Le stime della concessione di memoria si basano su:

  • Numero di righe (cardinalità)
  • Dimensione delle file (dimensione dei dati)
  • Numero di operatori simultanei che consumano memoria

Se viene scelto un piano parallelo, c'è un sovraccarico di memoria per elaborare gli scambi paralleli (distribuire, ridistribuire e raccogliere flussi), tuttavia le loro esigenze di memoria non vengono ancora calcolate allo stesso modo.

Operatori che consumano memoria

Gli operatori più comuni che richiedono memoria sono

  • Sorts
  • Hash (join, aggregati)
  • Loop nidificati ottimizzati

Gli operatori meno comuni che richiedono memoria sono inserimenti negli indici del negozio di colonne. Questi differiscono anche per il fatto che le concessioni di memoria sono attualmente moltiplicate per DOP per loro.

Le esigenze di memoria per gli ordinamenti sono in genere molto più elevate rispetto agli hash. Gli ordinamenti richiederanno almeno la dimensione stimata dei dati per una concessione di memoria, poiché devono ordinare tutte le colonne dei risultati in base agli elementi di ordinamento. Gli hash necessitano di memoria per creare una tabella hash, che non include tutte le colonne selezionate.

Esempi

Se eseguo questa query, intenzionalmente accennato a DOP 1, verranno richiesti 166 MB di memoria.

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

NOCCIOLINE

Se eseguo questa query (di nuovo, DOP 1), il piano cambierà e la concessione di memoria aumenterà leggermente.

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

NOCCIOLINE

Esistono due tipi e ora un Hash Join. La concessione di memoria aumenta leggermente per adattarsi alla generazione dell'hash, ma non raddoppia perché gli operatori di ordinamento non possono essere eseguiti contemporaneamente.

Se cambio la query per forzare l'unione di loop nidificati, la concessione raddoppierà per gestire gli ordinamenti simultanei.

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

NOCCIOLINE

La concessione di memoria raddoppia perché Nested Loop non è un operatore bloccante e Hash Join lo è.

Dimensione dei dati

Questa query seleziona i dati di stringa di diverse combinazioni. A seconda delle colonne selezionate, la dimensione della concessione di memoria aumenterà.

Il modo in cui la dimensione dei dati viene calcolata per i dati di stringa variabile è righe * 50% della lunghezza dichiarata della colonna. Questo vale per VARCHAR e NVARCHAR, sebbene le colonne NVARCHAR siano raddoppiate poiché memorizzano caratteri a doppio byte. Questo cambia in alcuni casi con il nuovo CE, ma i dettagli non sono documentati.

La dimensione dei dati è importante anche per le operazioni di hash, ma non nella stessa misura in cui lo fa per Sorts.

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

Ma che dire del parallelismo?

Se eseguo questa query in diversi DOP, la concessione di memoria non viene moltiplicata per 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 ?);

NOCCIOLINE

Ci sono lievi aumenti per gestire un numero maggiore di buffer paralleli per operatore di scambio e forse ci sono ragioni interne per cui le build di ordinamento e hash richiedono memoria aggiuntiva per gestire un DOP più elevato, ma chiaramente non è un fattore moltiplicatore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.