В SQL Server, как параллелизм меняет предоставление памяти?

9

Я слышал противоречивые вещи о предоставлении памяти для параллельных запросов на выборку:

  • Гранты памяти умножаются на DOP
  • Гранты памяти делятся на DOP

Что он?

Эрик Дарлинг
источник

Ответы:

10

Sup?

Для запросов SQL Server, которые требуют дополнительной памяти, предоставляются разрешения для последовательных планов. Если будет изучен и выбран параллельный план, память будет равномерно распределена между потоками.

Оценки предоставления памяти основаны на:

  • Количество рядов (количество элементов)
  • Размер строк (размер данных)
  • Количество одновременно работающих операторов памяти

Если выбран параллельный план, существуют некоторые издержки памяти для обработки параллельных обменов (распределения, перераспределения и сбора потоков), однако их потребности в памяти все еще не рассчитываются таким же образом.

Операторы, использующие память

Наиболее распространенные операторы, которые запрашивают память

  • Сорта
  • Хэши (объединения, агрегаты)
  • Оптимизированные вложенные циклы

Менее распространенными операторами, требующими памяти, являются вставки в индексы хранилища столбцов. Они также отличаются тем, что для них в настоящее время количество выделяемых памяти умножается на DOP.

Потребность в памяти для сортировки обычно намного выше, чем для хэшей. Сортировки будут запрашивать как минимум предполагаемый размер данных для предоставления памяти, так как им нужно отсортировать все столбцы результата по элементам порядка. Хешам нужна память для построения хеш-таблицы, которая включает не все выбранные столбцы.

Примеры

Если я выполню этот запрос, намеренно намекающий на DOP 1, он запросит 166 МБ памяти.

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

NUTS

Если я выполню этот запрос (снова DOP 1), план изменится, и объем памяти немного увеличится.

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

NUTS

Есть два вида, и теперь Hash Join. Предоставление памяти немного увеличивается для размещения хэш-сборки, но не удваивается, потому что операторы сортировки не могут работать одновременно.

Если я изменю запрос, чтобы принудительно соединить вложенные циклы, грант удвоится, чтобы справиться с одновременными сортировками.

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

NUTS

Предоставление памяти удваивается, потому что Nested Loop не является оператором блокировки, а Hash Join является.

Размер данных имеет значение

Этот запрос выбирает строковые данные различных комбинаций. В зависимости от того, какие столбцы я выберу, размер предоставления памяти будет увеличиваться.

Способ расчета размера данных для переменных строк - это строки * 50% от объявленной длины столбца. Это верно для VARCHAR и NVARCHAR, хотя столбцы NVARCHAR удваиваются, поскольку в них хранятся двухбайтовые символы. Это меняется в некоторых случаях с новым CE, но детали не задокументированы.

Размер данных также имеет значение для операций хеширования, но не в той же степени, как для сортировок.

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

Но как насчет параллелизма?

Если я выполню этот запрос в разных DOP, выделение памяти не умножается на 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 ?);

NUTS

Есть небольшие увеличения, чтобы справиться с большим количеством параллельных буферов на оператора обмена, и, возможно, есть внутренние причины, по которым сборки Sort и Hash требуют дополнительной памяти для работы с более высоким DOP, но это явно не фактор умножения.

Эрик Дарлинг
источник