本文詳細說明如何判斷 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]
都是外部數據表。
使用聯結下推(檢視執行計劃)
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;
聯結下推 (使用 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 中執行。