Я слышал противоречивые вещи о предоставлении памяти для параллельных запросов на выборку:
- Гранты памяти умножаются на DOP
- Гранты памяти делятся на DOP
Что он?
Я слышал противоречивые вещи о предоставлении памяти для параллельных запросов на выборку:
Что он?
Ответы:
Для запросов 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);
Если я выполню этот запрос (снова 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);
Есть два вида, и теперь 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);
Предоставление памяти удваивается, потому что 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 ?);
Есть небольшие увеличения, чтобы справиться с большим количеством параллельных буферов на оператора обмена, и, возможно, есть внутренние причины, по которым сборки Sort и Hash требуют дополнительной памяти для работы с более высоким DOP, но это явно не фактор умножения.