Joe*_*ish 7 sql-server execution-plan sql-server-2016
SQL Server 2014 引入了sys.dm_exec_query_profiles DMV,它提供了一种监视执行查询的实时进度的方法。最近我在查看 SQL Server 2016 SP1 中的一个有点复杂的查询,并注意到它sys.dm_exec_query_profiles
包含查询计划中不存在的额外节点。这些节点必须???
为physical_operator_name
:
对于查询的并行版本,只有一个隐藏节点。该节点有一个object_id
与嵌套循环连接的内表相关联。根据node_id
这里是节点应该出现的地方:
运行查询会MAXDOP 1
产生更多的隐藏节点。该???
节点出现在与之前相同的位置:
还有一个新的没有出现在平行计划中:
这些似乎只出现在一些嵌套循环连接周围。我不记得在 SQL Server 2014 上看到过这种行为。不幸的是,查询很复杂,我无法上传匿名计划。
这里发生了什么?为什么sys.dm_exec_query_profiles
报告没有显示在图形计划中的额外查询计划节点?
批处理模式适配器(位于行处理切换到批处理或其他方式的查询计划中)???
在 DMV 中显示为athread_id
为 0。但是,示例查询不使用批处理,因此不是原因在这里。
嵌套循环预取也可能导致sys.dm_exec_query_profiles
. 有一个用于禁用嵌套循环预取的记录跟踪标志:
跟踪标志 8744 禁用嵌套循环运算符的预取。
当 SQL Server 执行包含嵌套循环运算符的计划时,不正确使用此跟踪标志可能会导致额外的物理读取。有关嵌套循环运算符的详细信息,请参阅 SQL Server 2005 联机丛书中的“逻辑和物理运算符参考”主题。
如果我向查询添加查询提示,QUERYTRACEON 8744
则???
节点不再出现。
对于嵌套循环预取的可重现示例,我将借用 Paul White 在他的嵌套循环预取文章中针对 Adventure Works 的示例:
SELECT TOP (1000)
P.Name,
TH.TransactionID
FROM Production.Product AS P
JOIN Production.TransactionHistory AS TH
ON TH.ProductID = P.ProductID
WHERE
P.Name LIKE N'[K-P]%'
ORDER BY
P.Name,
TH.TransactionID;
Run Code Online (Sandbox Code Playgroud)
如果我对 SQL Server 2016 SP1 运行该查询并快速捕获输出,sys.dm_exec_query_profiles
我会得到以下结果:
SELECT TOP (1000)
P.Name,
TH.TransactionID
FROM Production.Product AS P
JOIN Production.TransactionHistory AS TH
ON TH.ProductID = P.ProductID
WHERE
P.Name LIKE N'[K-P]%'
ORDER BY
P.Name,
TH.TransactionID;
Run Code Online (Sandbox Code Playgroud)
如果我在 SQL Server 2014 中运行相同的查询,我会得到以下结果:
?????????????????????????????????????????????????????????????????????
? OBJECT_NAME ? physical_operator_name ? node_id ? thread_id ?
?????????????????????????????????????????????????????????????????????
? NULL ? Top ? 0 ? 0 ?
? NULL ? Nested Loops ? 1 ? 0 ?
? TransactionHistory ? ??? ? 2 ? 0 ?
? Product ? Index Seek ? 3 ? 0 ?
? TransactionHistory ? Index Seek ? 4 ? 0 ?
?????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,都会发生嵌套循环预取优化。似乎只有 SQL Server 2016 报告了它,但这可以解释为什么我从未在 SQL Server 2014 中看到过这种情况。