Gor*_*off 13 sql-server execution-plan database-internals union
在标准 SQL 中,union all不保证a 的结果按任何顺序排列。所以,像这样:
select 'A' as c union all select 'B'
Run Code Online (Sandbox Code Playgroud)
可以以任何顺序返回两行(尽管实际上在我知道的任何数据库上,'A' 都会出现在 'B' 之前)。
在 SQL Server 中,这变成了使用“串联”物理操作的执行计划。
我可以很容易地想象连接操作会扫描它的输入,返回任何有可用记录的输入。但是,我在网络上发现了以下声明(此处):
Query Processor 将按照操作符出现在计划中的顺序执行这个计划,第一个是最上面的,最后一个是最后一个。
问题:这在实践中是真的吗?这能保证是真的吗?
我还没有在 Microsoft 文档中找到任何参考资料,说明按顺序扫描输入,从第一个到最后一个。另一方面,每当我尝试运行它时,结果表明输入确实是按顺序处理的。
有没有办法让引擎一次处理多个输入?我的测试(使用比常量更复杂的表达式)是在支持并行的 8 核机器上进行的,并且大多数查询确实利用了并行性。
Str*_*DBA 11
不,Microsoft 没有保证行为的文档,因此不能保证。
此外,假设 Simple Talk 文章是正确的,并且 Concatenation 物理运算符始终按照计划中显示的顺序处理输入(很可能是正确的),则不能保证 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%'
Run Code Online (Sandbox Code Playgroud)
在 SQL Server 2012 Enterprise Edition 上,这会生成 24 行。忽略与常量相关的转换的错误匹配,有一种与连接物理运算符UNIAtoCON(Union All to Concatenation)相关的转换。因此,在物理运算符级别,似乎一旦选择了连接运算符,它将按照其派生自的逻辑 Union All 运算符的顺序进行处理。
事实上,这并不完全正确。存在优化后重写,可以在基于成本的优化完成后将输入重新排序到物理串联运算符。当串联受制于行目标时会出现一个示例(因此首先从更便宜的输入中读取可能很重要)。有关更多详细信息,请参阅Paul White 的UNION ALL优化。
后期物理重写在 SQL Server 2008 R2 之前和包括 SQL Server 2008 R2 中都有效,但回归意味着它不再适用于 SQL Server 2012 及更高版本。一个修复已发出的是恢复了这个改写为SQL Server 2014和更高版本(不是2012)与查询优化启用修补程序(如跟踪标志4199)。
但是关于 Logical Union All 运算符 ( UNIA) 呢?有一个UNIAReorderInputs转换,可以重新排序输入。还有两个物理运算符可用于实现逻辑 Union AllUNIAtoCON和UNIAtoMERGE(Union All to Merge Union)。
因此,查询优化器似乎可以对输入重新排序UNION ALL;然而,它似乎不是一个常见的转换(UNIAReorderInputs在我很容易访问的 SQL Server 上零使用。我们不知道会使优化器使用的情况UNIAReorderInputs;尽管它肯定会在计划指南或使用时使用计划提示用于强制使用上述行目标物理重新排序输入生成计划。
有没有办法让引擎一次处理多个输入?
Concatenation 物理运算符可以存在于计划的并行部分中。遇到一些困难,我能够使用以下查询生成具有并行连接的计划:
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)
Run Code Online (Sandbox Code Playgroud)
因此,在最严格的意义上,物理串联运算符似乎总是以一致的方式处理输入(顶部第一,底部第二);然而,优化器可以在选择物理运算符之前切换输入的顺序,或者使用合并联合而不是串联。
根据Craig Freedman的说法,连接运算符的执行顺序是有保证的。
请注意,当操作员有多个孩子时,孩子的顺序很重要。最上面的孩子是第一个孩子,而最下面的孩子是第二个。连接运算符按此顺序处理子项。
并来自在线书籍Showplan Logical and Physical Operators Reference
Concatenation 物理运算符有两个或多个输入和一个输出。串联将行从第一个输入流复制到输出流,然后对每个其他输入流重复此操作。
| 归档时间: |
|
| 查看次数: |
1585 次 |
| 最近记录: |