本文详细介绍了如何确定 PolyBase 查询是否受益于从下推到外部数据源。 有关外部下推的详细信息,请参阅 PolyBase 中的下推计算。
我的查询是否受益于外部下推?
下推计算可提高对外部数据源的查询性能。 某些计算任务将委托给外部数据源,而不是被带到 SQL Server。 特别是在筛选和连接下推的情况下,SQL Server 实例上的工作负荷可以大幅减少。
PolyBase 下推计算可以显著提高查询的性能。 如果 PolyBase 查询执行缓慢,则应检查 PolyBase 查询的下推是否发生。
在执行计划中可以观察到下推的三种不同情况:
- 过滤器谓词下推
- 加入下推
- 聚合下推
注释
使用 PolyBase 下推计算,可以向下推送到外部数据源存在限制:
- 某些 T-SQL 函数可能会阻止下推,有关详细信息,请参阅 PolyBase 功能和限制。
- 有关可以向下推送的 T-SQL 函数的列表,请参阅 PolyBase 中的下推计算。
引入了 SQL Server 2019(15.x)的两项新功能,使管理员能够确定 PolyBase 查询是否被推送到外部数据源:
- 查看 跟踪标志为 6408 的估计执行计划
- 在
read_command中查看sys.dm_exec_external_work动态管理视图
本文详细介绍了如何在三个下推方案中的每一个方案中使用这两个用例。
使用 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 中,远程查询计划以查询 2(sp_execute_memo_node_1) 的形式显示在估计的执行计划中,对应于查询 1 中的远程查询运算符。 例如:
在 Azure Data Studio 中,远程查询执行改为表示为单个查询计划。 例如:
没有筛选器谓词的下推(使用执行计划查看)
如果未发生筛选器谓词的下推,筛选器会位于外部运算符之后。
SSMS 的估计执行计划:
Azure Data Studio 的估计执行计划:
JOIN 操作下推
请考虑以下查询,该查询对同一外部数据源上的两个外部表使用 JOIN 运算符:
SELECT be.BusinessEntityID, bea.AddressID
FROM [Person].[BusinessEntity] AS be
INNER JOIN [Person].[BusinessEntityAddress] AS bea
ON be.BusinessEntityID = bea.BusinessEntityID;
如果将 JOIN 向下推送到外部数据源,则 Join 运算符将位于外部运算符之前。 在此示例中,这两个表都是[BusinessEntity][BusinessEntityAddress]外部表。
使用连接下推(通过执行计划可视化)
SSMS 的估计执行计划:
Azure Data Studio 的估计执行计划:
没有下推联接(查看执行计划)
如果未将 JOIN 向下推送到外部数据源,则 Join 运算符将在外部运算符之后。 在 SSMS 中,外部运算符位于查询计划中 sp_execute_memo_node,位于查询 1 中的远程查询运算符中。 在 Azure Data Studio 中,Join 运算符位于外部运算符之后。
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)及更高版本中,read_commandsys.dm_exec_external_work DMV 列显示发送到外部数据源的查询。 这允许你确定下推是否发生,但不会公开执行计划。 查看远程查询不需要 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方法的一个限制是 read_command DMV 中的字段限制为 4000 个字符。 如果查询足够长,read_command 可能会在你看到 WHERE/JOIN/聚合函数之前被截断,而 read_command 可能遭遇类似情况。
筛选条件下推(使用 DMV 查看)
请考虑上一个筛选器谓词示例中使用的查询:
SELECT *
FROM [Person].[BusinessEntity] be
WHERE be.BusinessEntityID = 17907;
使用筛选器下推(使用 DMV 查看)
可以通过检查 read_command DMV 中的值来判断筛选器谓词的下推是否发生。 你将看到类似于以下示例的内容:
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 端。
将 JOIN 下推(通过 DMV 查看)
请考虑上一 JOIN 示例中使用的查询:
SELECT be.BusinessEntityID, bea.AddressID
FROM [Person].[BusinessEntity] be
INNER JOIN [Person].[BusinessEntityAddress] bea ON be.BusinessEntityID = bea.BusinessEntityID;
使用下推联接(通过 DMV 查看)
如果 JOIN 向下推送到外部数据源,你将看到如下内容:
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 子句,因此将 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 中执行的。