在 SQL Server 中,并行性如何改变内存授予?

Eri*_*ing 9 sql-server parallelism memory-grant

我听说过关于并行选择查询的内存授予的相互矛盾的事情:

  • 内存授权乘以 DOP
  • 记忆补助除以 DOP

是哪个?

Eri*_*ing 11

苏?

对于需要额外内存的 SQL Server 查询,会为串行计划派生授权。如果探索和选择并行计划,内存将在线程之间平均分配。

内存授予估计基于:

  • 行数(基数)
  • 行大小(数据大小)
  • 并发内存消耗运算符的数量

如果选择并行计划,则处理并行交换(分发、重新分发和收集流)会产生一些内存开销,但是它们的内存需求仍然不是以相同的方式计算的。

内存消耗运算符

要求内存的最常见运算符是

  • 排序
  • 哈希(连接、聚合)
  • 优化的嵌套循环

需要内存的不太常见的运算符是插入到列存储索引。它们的不同还在于内存授予当前乘以它们的 DOP。

排序的内存需求通常比散列高得多。排序将要求至少估计的内存授予数据大小,因为它们需要按排序元素对所有结果列进行排序。哈希需要内存来构建哈希表,哈希表不包括所有选定的列。

例子

如果我运行这个查询,故意暗示 DOP 1,它将要求 166 MB 的内存。

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

坚果

如果我运行这个查询(再次,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);
Run Code Online (Sandbox Code Playgroud)

坚果

有两种排序,现在是哈希联接。内存授予稍微增加以适应散列构建,但它不会加倍,因为 Sort 运算符不能同时运行。

如果我更改查询以强制嵌套循环连接,则授权将加倍以处理并发排序。

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);
Run Code Online (Sandbox Code Playgroud)

坚果

内存授予加倍,因为嵌套循环不是阻塞运算符,而 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);
Run Code Online (Sandbox Code Playgroud)

但是并行性呢?

如果我在不同的 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 ?);
Run Code Online (Sandbox Code Playgroud)

坚果

每个交换操作符处理更多并行缓冲区的情况略有增加,也许存在内部原因,即 Sort 和 Hash 构建需要额外的内存来处理更高的 DOP,但这显然不是一个乘数。