如何判斷是否發生外部下推
本文詳細會說明如何判斷 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
),並對應至查詢 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]
都是外部表格。
透過 JOIN 下推 (檢視執行計畫)
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) 和更新版本中,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
可能會在看到 read_command
中的 WHERE/JOIN/aggregation 函式之前被截斷。
篩選述詞下推 (使用 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 端。
JOIN 下推 (使用 DMV 檢視)
請考慮先前 JOIN 範例中使用的查詢:
SELECT be.BusinessEntityID, bea.AddressID
FROM [Person].[BusinessEntity] be
INNER JOIN [Person].[BusinessEntityAddress] bea ON be.BusinessEntityID = bea.BusinessEntityID;
使用 JOIN 下推 (使用 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 擷取。
沒有 JOIN 下推 (使用 DMV 檢視)
如果未發生 JOIN 下推,會看到針對外部資料來源執行兩個不同的查詢:
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 中執行。