Sql-Server

僅在使用 SESSION_CONTEXT 時在 Azure 中進行非並行計劃

  • March 12, 2022

我正在觀察本地電腦和 Azure SQL 上的查詢計劃之間的奇怪差異。我正在嘗試實現行級安全性,我從 SESSION_CONTEXT 讀取使用者標識符,然後在 TVF 中檢查使用者是否具有訪問權限。

在我的本地機器上 - SQL Server 2019 Developer edition,兼容級別為 150 的數據庫,查詢計劃符合預期。但是,當我在也是 150 兼容級別的 Azure DB 上執行它時,我只能獲得帶有NonParallelPlanReason="NonParallelizableIntrinsicFunction". 我嘗試了一個超大規模數據庫以及彈性池中的一個數據庫,結果在兩個數據庫上都是相同的。

您可以使用以下程式碼重現它:

CREATE TABLE Users (
   UserIdentifier nvarchar(100) PRIMARY KEY CLUSTERED
)

INSERT INTO Users (UserIdentifier) VALUES ('MyUserIdentifier')

CREATE TABLE TableWithRLS (
   Id int NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
   DataColumn nvarchar(100) NULL
)

INSERT INTO TableWithRLS (DataColumn) 
SELECT TOP 10000000 A.[name] FROM sys.all_columns  AS A
CROSS JOIN sys.all_columns  AS B
CROSS JOIN sys.all_columns  AS C


CREATE OR ALTER FUNCTION CheckAccess (@userIdentifier varchar(100))
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
   SELECT TOP 1 1 AS HasAccess FROM dbo.Users WHERE UserIdentifier = @userIdentifier

EXEC sp_set_session_context N'UserIdentifier', N'MyUserIdentifier', 1

-- This query gets always non-parallel query plan on Azure
SELECT MAX(DataColumn) FROM TableWithRLS AS X
CROSS APPLY CheckAccess(CAST(SESSION_CONTEXT(N'UserIdentifier') AS nvarchar(100)))

當我首先將會話上下文中的值選擇到變數中時,即使在 Azure 中它也會生成可並行化的查詢計劃。

DECLARE @userIdentifier AS nvarchar(100) = CAST(SESSION_CONTEXT(N'UserIdentifier') AS nvarchar(100))
SELECT MAX(DataColumn) FROM TableWithRLS AS X
CROSS APPLY CheckAccess(@userIdentifier)

不幸的是,我不能這樣做(或者至少我不知道該怎麼做),因為我需要一個內聯 TVF。

Azure 的查詢計劃:https ://www.brentozar.com/pastetheplan/?id=ByxZm45e9

本地查詢計劃:https ://www.brentozar.com/pastetheplan/?id=BylHXV9lc

Azure 中的 SESSION_CONTEXT 實現有什麼不同可能導致這種情況嗎?或者有沒有人有任何其他想法可能是什麼問題?

Azure 中的 SESSION_CONTEXT 實現有什麼不同可能導致這種情況嗎?

是的。儘管 Azure SQL 數據庫和 SQL Server 是從一個通用程式碼庫建構的,但一個領先於另一個的情況並不少見。儘管微軟在過去幾年進行了行銷,但並不總是領先於 Azure 版本。

使用時禁止並行計劃是目前在 Azure 中啟用SESSION_CONTEXT的功能標誌 ( DisableSessionContextParallelPlan ),無法將其關閉。它可以在 SQL Server 上使用未記錄的跟踪標誌 11042 在查詢、會話、全域和啟動級別啟用。

使用 Stack Overflow 展示數據庫(任何並行查詢都可以):

EXECUTE sys.sp_set_session_context 
   @key = N'key', 
   @value = 123,
   @read_only = 1;

SELECT COUNT_BIG(*) 
FROM dbo.Badges AS B 
WHERE B.UserId = CONVERT(integer, SESSION_CONTEXT(N'Key'))
OPTION (QUERYTRACEON 11042);

查詢是並行的,沒有 SQL Server 上的跟踪標誌。

這些選項通常添加到預覽功能中,作為對罕見錯誤情況或存在安全風險的響應。

SQL Server 2019 CU14 中發布了在並行計劃中使用時錯誤結果的錯誤修復。SESSION_CONTEXT


來自Lukas.Navratil

我與 MS 取得了聯繫,並且在使用並行計劃時確實存在問題SESSION_CONTEXT,因此他們使用跟踪標誌禁用了它們。它已經修復,但跟踪標誌計劃在下一個全球版本中刪除,所以在幾個月內它應該有望重新啟用。

引用自:https://dba.stackexchange.com/questions/308059