级联物理操作:是否保证执行顺序?


12

在标准SQL中,union all不能保证a的结果以任何顺序排列。因此,类似:

select 'A' as c union all select 'B'

可以按任何顺序返回两行(尽管实际上,在我所知道的任何数据库上,“ A”都将排在“ B”之后)。

在SQL Server中,这变成使用“串联”物理操作的执行计划。

我很容易想到,连接操作将扫描其输入,并返回具有可用记录的任何输入。但是,我在网上(此处)找到了以下声明:

查询处理器将按照操作员出现在计划中的顺序执行该计划,第一个是最上一个,最后一个是最后一个。

问题:实际上是这样吗?这保证是真的吗?

我没有在Microsoft文档中找到任何参考,从头到尾按顺序扫描输入。另一方面,每当我尝试运行它时,结果表明实际上确实按顺序处理了输入。

有没有一种方法可以让引擎一次处理多个输入?我的测试(使用比常量更复杂的表达式)是在启用了并行的8核计算机上进行的,大多数查询的确利用了并行性。

Answers:


10

,Microsoft没有提供任何文档来保证该行为,因此不能保证

此外,假设“简单谈话”文章是正确的,并且“串联”物理运算符始终按计划中显示的顺序处理输入(很可能是真的),则不能保证SQL Server 始终会生成保持相同的计划。查询文本和查询计划之间的顺序,您的情况只会稍微好一些。

我们可以对此进行进一步调查。如果查询优化器能够对连接运算符输入进行重新排序,则未记录的DMV中应存在sys.dm_exec_query_transformation_stats与该优化相对应的行。

SELECT * FROM sys.dm_exec_query_transformation_stats 
    WHERE name LIKE '%CON%' OR name LIKE '%UNIA%'

在SQL Server 2012 Enterprise Edition上,这将产生24行。忽略与常量相关的转换的错误匹配,存在一种与级联物理运算符UNIAtoCON(联合到级联)有关的转换。因此,在物理运算符级别,似乎选择了串联运算符后,将按照从其派生的逻辑Union All运算符的顺序对其进行处理。


实际上那不是很正确。存在基于优化的后重写,可以在基于成本的优化完成后将输入重新排序到物理级联运算符。当串联受行目标约束时发生一个示例(因此,首先从便宜的输入中读取数据可能很重要)。有关更多详细信息,请参见Paul White的《UNION ALL优化》

后来的物理重写在SQL Server 2008 R2之前(包括SQL Server 2008 R2)都起作用,但是回归表明它不再适用于SQL Server 2012及更高版本。一个修复已发出的是恢复了这个改写为SQL Server 2014和更高版本(不是2012)与查询优化启用修补程序(如跟踪标志4199)。


但是关于“逻辑联合所有”运算符(UNIA)?有一个UNIAReorderInputs转换,可以重新排列输入的顺序。还有两个物理运算符可用于实现逻辑“ Union All” UNIAtoCON和“ UNIAtoMERGEUnion All to Merge Union”。

因此,查询优化器似乎可以对a的输入重新排序UNION ALL。但是,这似乎不是一个常见的转换(UNIAReorderInputs我可以轻松访问的SQL Server上的零使用。我们不知道会导致优化程序使用的情况UNIAReorderInputs;尽管在计划指南或使用时肯定会使用它)计划提示用于强制使用上述行目标物理重新排序输入生成的计划。

有没有一种方法可以让引擎一次处理多个输入?

串联物理运算符可以存在于计划的并行部分中。遇到一些困难,我能够使用以下查询生成具有并行连接的计划:

SELECT userid, regdate  FROM (  --Users table is around 3mil rows
    SELECT  userid, RegDate FROM users WHERE userid > 1000000
    UNION 
    SELECT  userid, RegDate FROM users WHERE userid < 1000000
    UNION all
    SELECT userid, RegDate FROM users WHERE userid < 2000000
    ) d ORDER BY RegDate OPTION (RECOMPILE)

因此,从最严格的意义上讲,物理级联运算符似乎确实总是以一致的方式处理输入(从上到下,从下到上)。但是,优化器可以在选择物理运算符之前切换输入的顺序,或者使用合并联合而不是串联。


8

根据Craig Freedman所说,可以确保级联运算符的执行顺序。

从他的博客文章“ 在MSDN博客上查看查询计划 ”:

请注意,当操作员有多个孩子时,孩子的顺序很重要。最高的孩子是第一个孩子,而最低的孩子是第二个孩子。串联运算符按此顺序处理子级。

以及在线书籍Showplan逻辑和物理操作员参考

串联物理运算符具有两个或多个输入和一个输出。串联将行从第一个输入流复制到输出流,然后对每个其他输入流重复此操作。


那句话与我一直在寻找的很接近。我很乐意从按该顺序执行到按该顺序返回的飞跃-尽管在这种情况下文档阻止并行处理令人失望。
Gordon Linoff 2014年

2

社区Wiki答案

我不知道您是否可以证明一种观察到的行为总是能够得到保证,无论哪种方式都可以保证,除非您可以提出反例。如果没有这种方法,确定返回结果的顺序的方法当然是添加ORDER BY

我不知道是否有一个“修复程序”,或者是否需要修复程序,如果您可以证明在某些情况下查询是以不同顺序处理的。

缺少任何明确的官方文档对我来说,您不应依赖于此。这正是一种是让人们陷入困境与事ORDER BY的看法,并GROUP BY没有ORDER BY8年前,SQL Server 2005中的优化器发布时。

有了SQL Server较新版本中的所有新功能(还有更多功能),即使您认为自己可以保证今天的特定行为,我也不会指望它成立(直到有文档证明这样做)。

即使您不依赖此行为,您将如何处理结果?无论如何,我不会把被外人简单对话文章官员。就我们所知,这仅仅是基于观察的猜测。

Microsoft永远不会发布官方文档,说不能保证'x' 做'y'。这是我们在将近十年后仍然难以说服人们他们不能依靠观察到的顺序的原因之一ORDER BY-没有文档说明“不能保证”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.