如何判断是否发生了外部下推
本文详细介绍了如何确定 PolyBase 查询是否受益于到外部数据源的下推。 有关外部下推的详细信息,请参阅 PolyBase 中的下推计算。
我的查询是否受益于外部下推?
下推计算提高了外部数据源上的查询性能。 某些计算任务会被委托给外部数据源,而不是被引入 SQL Server。 尤其是在筛选和联接下推的情况下,可大大减少 SQL Server 实例上的工作负载。
PolyBase 下推计算可显著提高查询的性能。 如果 PolyBase 查询的执行速度缓慢,则应确定是否正在发生 PolyBase 查询下推。
下面是在执行计划中可观察到下推的三个不同场景:
- 筛选谓词下推
- 联接下推
- 聚合下推
注意
使用 PolyBase 下推计算可以下推到外部数据源的内容存在以下限制:
- 某些 T-SQL 函数可阻止下推,有关详细信息,请参阅 PolyBase 功能和限制。
- 有关其他可下推的 T-SQL 函数的列表,请参阅 PolyBase 中的下推计算。
引入了 SQL Server 2019 (15.x) 的两项新功能,以使管理员能够确定 PolyBase 查询是否被下推到外部数据源:
- 查看带有跟踪标志 6408 的估计的执行计划
- 查看 sys.dm_exec_external_work 动态管理视图中的
read_command
本文详细介绍了如何针对这三个下推场景中的每一个使用这两个用例。
使用 TF6408
默认情况下,估计的执行计划不会公开远程查询计划,你只会看到远程查询运算符对象。 例如,来自 SQL Server Management Studio (SSMS) 的估计的执行计划:
或者,在 Azure Data Studio 中:
从 SQL Server 2019 (15.x) 开始,可使用 DBCC TRACEON 全局启用新的跟踪标志 6408。 例如:
DBCC TRACEON (6408, -1);
此跟踪标志仅适用于估计的执行计划,对实际的执行计划不起作用。 此跟踪标志公开有关远程查询运算符的信息,这些信息显示在远程查询阶段发生的情况。
如箭头方向所示,从右到左读取执行计划。 如果一个运算符位于另一个运算符的右侧,则称其在另一个运算符“之前”。 如果一个运算符位于另一个运算符的左侧,则称其在另一个运算符“之后”。
- 在 SSMS 中,突出显示查询,然后从工具栏中选择“显示估计的执行计划”或使用 Ctrl+L。
- 在 Azure Data Studio 中,突出显示查询并选择“说明”。 然后考虑以下场景来确定是否发生了下推。
下面的每个示例都包含来自 SSMS 和 Azure Data Studio 的输出。
筛选谓词下推(查看执行计划)
考虑以下查询,它在 WHERE 子句中使用筛选谓词:
SELECT *
FROM [Person].[BusinessEntity] AS be
WHERE be.BusinessEntityID = 17907;
如果发生筛选谓词下推,则筛选运算符将位于外部运算符之前。 当筛选运算符位于外部运算符之前,表明筛选发生在从外部数据源中选中之前,指示已下推筛选谓词。
包含筛选谓词下推(查看执行计划)
启用跟踪标志 6408 后,你现在可以在估计的执行计划输出中看到其他信息。 SSMS 和 Azure Data Studio 的输出不同。
在 SSMS 中,远程查询计划在估计的执行计划中显示为 Query 2 (sp_execute_memo_node_1
),对应于 Query 1 中的 Remote Query 运算符。 例如:
在 Azure Data Studio 中,远程查询执行改为以单个查询计划表示。 例如:
不包含筛选谓词下推(查看执行计划)
如果未发生筛选谓词下推,则筛选运算符将位于外部运算符之后。
来自 SSMS 的估计的执行计划:
来自 Azure Data Studio 的估计的执行计划:
联接下推
请考虑以下查询,该查询对同一外部数据源上的两个外部表使用 JOIN 运算符:
SELECT be.BusinessEntityID, bea.AddressID
FROM [Person].[BusinessEntity] AS be
INNER JOIN [Person].[BusinessEntityAddress] AS bea
ON be.BusinessEntityID = bea.BusinessEntityID;
如果将联接下推到外部数据源,则联接运算符将位于外部运算符之前。 在此示例中,[BusinessEntity]
和 [BusinessEntityAddress]
都是外部表。
包含联接下推(查看执行计划)
来自 SSMS 的估计的执行计划:
来自 Azure Data Studio 的估计的执行计划:
不包含联接下推(查看执行计划)
如果未将联接下推到外部数据源,则联接运算符将位于外部运算符之后。 在 SSMS 中,外部运算符位于 sp_execute_memo_node
的查询计划中,该计划位于 Query 1 的远程查询运算符中。 在 Azure Data Studio 中,联接运算符位于外部运算符之后。
来自 SSMS 的估计的执行计划:
来自 Azure Data Studio 的估计的执行计划:
聚合下推(查看执行计划)
考虑使用聚合函数的以下查询:
SELECT SUM([Quantity]) as Quant
FROM [AdventureWorks2022].[Production].[ProductInventory];
包含聚合下推(查看执行计划)
如果发生聚合下推,则聚合运算符位于外部运算符之前。 当聚合运算符位于外部运算符之前,表明聚合发生在从外部数据源中选中之前,指示已下推聚合。
来自 SSMS 的估计的执行计划:
来自 Azure Data Studio 的估计的执行计划:
不包含聚合下推(查看执行计划)
如果未发生聚合下推,则聚合运算符将位于外部运算符之后。
来自 SSMS 的估计的执行计划:
来自 Azure Data Studio 的估计的执行计划:
使用 DMV
在 SQL Server 2019 (15.x) 及更高版本中,sys.dm_exec_external_work DMV 的 read_command
列显示发送到外部数据源的查询。 这样你就可以确定是否发生了下推,但不会公开执行计划。 查看远程查询不需要 TF6408。
注意
对于 Hadoop 和 Azure 存储,read_command
始终返回 NULL
。
可以执行以下查询并使用 start_time
/end_time
和 read_command
来识别正在调查的查询:
SELECT execution_id, start_time, end_time, read_command
FROM sys.dm_exec_external_work
ORDER BY execution_id desc;
注意
sys.dm_exec_external_work 方法存在一个限制,即 DMV 中的 read_command
字段限制为 4000 个字符。 如果查询足够长,则在你看到 read_command
中的 WHERE/JOIN/aggregation 函数之前,read_command
可能会被截断。
筛选谓词下推(查看 DMV)
考虑前面筛选谓词示例中使用的查询:
SELECT *
FROM [Person].[BusinessEntity] be
WHERE be.BusinessEntityID = 17907;
包含筛选下推(查看 DMV)
通过检查 DMV 中的 read_command
,判断是否发生筛选谓词下推。 你会看到类似于以下示例的内容:
SELECT [T1_1].[BusinessEntityID] AS [BusinessEntityID], [T1_1].[rowguid] AS [rowguid],
[T1_1].[ModifiedDate] AS [ModifiedDate] FROM
(SELECT [T2_1].[BusinessEntityID] AS [BusinessEntityID], [T2_1].[rowguid] AS [rowguid],
[T2_1].[ModifiedDate] AS [ModifiedDate]
FROM [AdventureWorks2022].[Person].[BusinessEntity] AS T2_1
WHERE ([T2_1].[BusinessEntityID] = CAST ((17907) AS INT))) AS T1_1;
WHERE 子句位于发送到外部数据源的命令中,这意味着正在外部数据源中对筛选谓词进行计算。 对数据集的筛选发生在外部数据源中,并且 PolyBase 仅检索筛选后的数据集。
不包含筛选下推(查看 DMV)
如果未发生下推,则将看到如下内容:
SELECT "BusinessEntityID","rowguid","ModifiedDate" FROM "AdventureWorks2022"."Person"."BusinessEntity"
发送到外部数据源的命令中没有 WHERE 子句,因此不会下推筛选谓词。 PolyBase 检索数据集后,会在 SQL Server 端对整个数据集进行筛选。
联接下推(查看 DMV)
考虑前面联接示例中使用的查询:
SELECT be.BusinessEntityID, bea.AddressID
FROM [Person].[BusinessEntity] be
INNER JOIN [Person].[BusinessEntityAddress] bea ON be.BusinessEntityID = bea.BusinessEntityID;
包含联接下推(查看 DMV)
如果将联接下推到外部数据源,你将看到如下内容:
SELECT [T1_1].[BusinessEntityID] AS [BusinessEntityID], [T1_1].[AddressID] AS [AddressID]
FROM (SELECT [T2_2].[BusinessEntityID] AS [BusinessEntityID], [T2_1].[AddressID] AS [AddressID]
FROM [AdventureWorks2022].[Person].[BusinessEntityAddress] AS T2_1
INNER JOIN [AdventureWorks2022].[Person].[BusinessEntity] AS T2_2
ON ([T2_1].[BusinessEntityID] = [T2_2].[BusinessEntityID])) AS T1_1;
JOIN 子句在位于发送到外部数据源的命令中,因此会下推联接。 数据集上的联接发生在外部数据源中,并且 PolyBase 仅检索与联接条件匹配的数据集。
不包含联接下推(查看 DMV)
如果未发生联接下推,你将看到对外部数据源执行两个不同的查询:
SELECT [T1_1].[BusinessEntityID] AS [BusinessEntityID], [T1_1].[AddressID] AS [AddressID]
FROM [AdventureWorks2022].[Person].[BusinessEntityAddress] AS T1_1;
SELECT [T1_1].[BusinessEntityID] AS [BusinessEntityID] FROM [AdventureWorks2022].[Person].[BusinessEntity] AS T1_1;
PolyBase 检索两个数据集后,会在 SQL Server 端发生这两个数据集的联接。
聚合下推(查看 DMV)
考虑使用聚合函数的以下查询:
SELECT SUM([Quantity]) as Quant
FROM [AdventureWorks2022].[Production].[ProductInventory];
包含聚合下推(查看 DMV)
如果发生聚合下推,你将在 read_command
中看到聚合函数。 例如:
SELECT [T1_1].[col] AS [col] FROM (SELECT SUM([T2_1].[Quantity]) AS [col]
FROM [AdventureWorks2022].[Production].[ProductInventory] AS T2_1) AS T1_1
聚合函数位于发送到外部数据源的命令中,因此会下推聚合。 聚合发生在外部数据源中,并且 PolyBase 仅检索聚合后的数据集。
不包含聚合下推(查看 DMV)
如果未发生聚合下推,你将不会在 read_command
中看到聚合函数。 例如:
SELECT "Quantity" FROM "AdventureWorks2022"."Production"."ProductInventory"
PolyBase 检索到未经聚合的数据集后,会在 SQL Server 中执行聚合。