Wie ändert Parallelität in SQL Server Speicherzuschüsse?

9

Ich habe widersprüchliche Dinge über Speicherzuweisungen für parallele Auswahlabfragen gehört:

  • Speicherzuschüsse werden mit DOP multipliziert
  • Speicherzuschüsse werden durch DOP geteilt

Welches ist es?

Erik Darling
quelle

Antworten:

10

Sup?

Für SQL Server-Abfragen, die zusätzlichen Speicher benötigen, werden Zuschüsse für serielle Pläne abgeleitet. Wenn ein paralleler Plan untersucht und ausgewählt wird, wird der Speicher gleichmäßig auf die Threads aufgeteilt.

Schätzungen für die Speicherzuweisung basieren auf:

  • Anzahl der Zeilen (Kardinalität)
  • Zeilengröße (Datengröße)
  • Anzahl der gleichzeitig speicherverbrauchenden Operatoren

Wenn ein paralleler Plan ausgewählt wird, entsteht ein gewisser Speicheraufwand für die Verarbeitung paralleler Austausche (Verteilen, Umverteilen und Sammeln von Streams). Der Speicherbedarf wird jedoch immer noch nicht auf die gleiche Weise berechnet.

Speicherverbrauchende Operatoren

Die häufigsten Operatoren, die nach Speicher fragen, sind

  • Sorten
  • Hashes (Joins, Aggregate)
  • Optimierte verschachtelte Schleifen

Weniger gebräuchliche Operatoren, die Speicher benötigen, sind Einfügungen in Spaltenspeicherindizes. Diese unterscheiden sich auch darin, dass Speicherzuweisungen derzeit für sie mit DOP multipliziert werden.

Der Speicherbedarf für Sortierungen ist normalerweise viel höher als für Hashes. Sortierungen fordern mindestens die geschätzte Datengröße für eine Speicherzuweisung an, da alle Ergebnisspalten nach Ordnungselementen sortiert werden müssen. Hashes benötigen Speicher, um eine Hash-Tabelle zu erstellen, die nicht alle ausgewählten Spalten enthält.

Beispiele

Wenn ich diese Abfrage ausführe, die absichtlich auf DOP 1 hingewiesen wurde, werden 166 MB Speicher benötigt.

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

NÜSSE

Wenn ich diese Abfrage ausführe (erneut DOP 1), ändert sich der Plan und die Speicherzuweisung steigt leicht an.

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

NÜSSE

Es gibt zwei Sorten und jetzt einen Hash Join. Die Speicherzuweisung erhöht sich ein wenig, um den Hash-Build aufzunehmen, verdoppelt sich jedoch nicht, da die Sortieroperatoren nicht gleichzeitig ausgeführt werden können.

Wenn ich die Abfrage ändere, um einen Join mit verschachtelten Schleifen zu erzwingen, wird die Berechtigung verdoppelt, um die gleichzeitigen Sortierungen zu verarbeiten.

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

NÜSSE

Die Speicherzuweisung verdoppelt sich, da Nested Loop kein blockierender Operator ist und Hash Join.

Größe der Datenangelegenheiten

Diese Abfrage wählt Zeichenfolgendaten verschiedener Kombinationen aus. Abhängig davon, welche Spalten ich auswähle, wird die Größe der Speicherzuweisung erhöht.

Die Art und Weise, wie die Datengröße für variable Zeichenfolgendaten berechnet wird, beträgt Zeilen * 50% der deklarierten Länge der Spalte. Dies gilt für VARCHAR und NVARCHAR, obwohl NVARCHAR-Spalten verdoppelt werden, da sie Doppelbytezeichen speichern. Dies ändert sich in einigen Fällen mit dem neuen CE, Details werden jedoch nicht dokumentiert.

Die Größe der Daten ist auch für Hash-Operationen von Bedeutung, jedoch nicht in demselben Maße wie für 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);

Aber was ist mit Parallelität?

Wenn ich diese Abfrage bei verschiedenen DOPs ausführe, wird die Speicherzuweisung nicht mit DOP multipliziert.

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

NÜSSE

Es gibt leichte Erhöhungen, um mit mehr parallelen Puffern pro Austauschoperator fertig zu werden, und vielleicht gibt es interne Gründe dafür, dass die Builds Sort und Hash zusätzlichen Speicher benötigen, um mit höherem DOP fertig zu werden, aber dies ist eindeutig kein Multiplikationsfaktor.

Erik Darling
quelle