5

首先,来自BOL

修改变量的查询不会生成并行查询执行计划。修改非常大的表变量或复杂查询中的表变量时,性能可能会受到影响。在这些情况下,请考虑改用临时表。有关详细信息,请参阅创建表 (Transact-SQL)。读取变量而不修改它们的查询仍然可以并行化。

这似乎很清楚。读取表变量而不修改它们的查询仍然可以并行化。

但后来在SQL Server Storage Engine上,另一个有名的消息来源,Sunil Agarwal 在 2008 年 3 月 30 日关于 tempdb 的一篇文章中说:

涉及表变量的查询不会生成并行计划。

Sunil 是在解释 BOL re: INSERT,还是 FROM 子句中存在表变量会阻止并行性?如果是这样,为什么?

我正在特别考虑控制表用例,其中您将一个小控制表连接到一个较大的表,以映射值,充当过滤器,或两者兼而有之。

谢谢!

4

4 回答 4

5

好的,我有一个并行选择,但不在表变量上

我已经匿名了,并且:

  • BigParallelTable 是 900k 行和宽
  • 由于遗留原因,BigParallelTable 被部分非规范化(稍后我会修复它,保证)
  • BigParallelTable 经常生成并行计划,因为它并不理想并且“昂贵”
  • SQL Server 2005 x64,SP3,内部版本 4035,16 核

查询+计划:

DECLARE @FilterList TABLE (bar varchar(100) NOT NULL)

INSERT @FilterList (bar)
SELECT 'val1' UNION ALL 'val2' UNION ALL 'val3'

--snipped

SELECT
     *
FROM
    dbo.BigParallelTable BPT
    JOIN
    @FilterList FL ON BPT.Thing = FL.Bar

StmtText
  |--Parallelism(Gather Streams)
       |--Hash Match(Inner Join, HASH:([FL].[bar])=([BPT].[Thing]), RESIDUAL:(@FilterList.[bar] as [FL].[bar]=[MyDB].[dbo].[BigParallelTable].[Thing] as [BPT].[Thing]))
            |--Parallelism(Distribute Streams, Broadcast Partitioning)
            |    |--Table Scan(OBJECT:(@FilterList AS [FL]))
            |--Clustered Index Scan(OBJECT:([MyDB].[dbo].[BigParallelTable].[PK_BigParallelTable] AS [BPT]))

现在,考虑一下,表变量几乎总是表扫描,没有统计信息,并且假设一行“估计行数 = 1”,“实际.. = 3”。

我们是否可以声明表变量不并行使用,但包含计划可以在其他地方使用并行?所以BOL是正确的,SQL Storage那篇文章是错误的

于 2009-10-30T07:58:29.523 回答
5

显示表变量本身的并行运算符的简单示例。

DECLARE @T TABLE
(
X INT
)
INSERT INTO @T
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM master..spt_values v1,master..spt_values v2;

WITH E8(N)
     AS (SELECT 1
         FROM   @T a,
                @T b),
     Nums(N)
     AS (SELECT TOP (1000000) ROW_NUMBER() OVER (ORDER BY (SELECT 0))
         FROM   E8)
SELECT COUNT(N)
FROM   Nums
OPTION (RECOMPILE)  

计划

于 2011-11-23T13:17:49.730 回答
2

[在这里回答我自己的问题,所以我可以适当地提出相关的报价......]

Boris B,来自MSDN SQL Server 论坛上的一个线程:

使用表变量的只读查询仍然可以并行化。涉及修改的表变量的查询按顺序运行。我们将更正在线图书中的声明。(临时添加)

和:

请注意,有两种并行性支持:

A. 操作员可以/不能在并行线程中

B. 查询可以/不能并行运行,因为该运算符存在于树中。

B 是 A 的超集。

据我所知,表变量不是B,可能是A。

另一个相关引用,re:非内联 T-SQL TVF:

如果 TVF 输入是运行时常量(例如变量和参数),则考虑非内联 T-SQL TVF...进行并行处理。如果输入是一列(来自交叉应用),则对整个语句禁用并行性。

于 2009-10-30T15:41:15.610 回答
1

我的理解是,对于 UPDATE/DELETE/INSERT 操作,表变量的并行性被阻止,但对于 SELECT 则不然。当然,证明这一点比仅仅假设要困难得多。:-)

于 2009-10-29T20:58:11.380 回答