Sql-Server

SQL Server 2017:交錯執行如何工作?

  • October 4, 2017

交錯執行是2017 年查詢處理器中一系列功能的一部分,其中包括:

那麼交錯執行是如何工作的呢?

魔鬼在表變數

交錯執行旨在糾正多語句表值函式中錯誤估計的基數。

在 SQL Server 的早期版本中,這些函式總是會產生相當低劣的估計:

  • 2014 年、2016 年:100 行
  • 2005 - 2012:1 行

不用說,這在加入其他表時可能會導致很多問題。

雖然從表變數中選擇數據本身不會抑制並行性,但低行估計通常會導致查詢成本低,而不會考慮並行性。

使用 Interleaved Execution,基數估計會暫停,MSTVF 的子樹會被執行,並以更準確的基數估計重新開始優化。

我如何知道我的 MSTVF 是否收到交錯執行。

與自適應聯接一樣,查詢計劃中會註明交錯執行。與 Adaptive Joins 不同,至少在撰寫本文時,估計的計劃中沒有註明。

具有交錯執行的 MSTVF 的計劃形狀與其中包含 MSTVF 的典型計劃有點不同。

您將在計劃頂部看到表值函式運算符,以及 TVF 運算符通常位於圖形計劃中的表變數的掃描。

堅果

將滑鼠懸停在 TVF 運算符上時,您會看到屬性IsInterleavedExecuted設置為 True,以及可能非常接近真實情況的估計行數。歡呼。

當不發生交錯執行時,是否有任何擴展事件需要排除故障?

是的,一大堆:

堅果

請注意,其中一些位於調試通道中,在搜尋要擴展的事件時預設情況下未選擇該通道。

交錯執行是否需要列儲存索引?

不,他們會以任何方式工作。這是一個例子:

SELECT u.Id, mj.*
FROM   dbo.Users_cx AS u --ColumnStore
JOIN   dbo.MultiStatementTVF_Join(0) AS mj
ON mj.UserId = u.Id
WHERE  u.LastAccessDate >= '2016-12-01';


SELECT u.Id, mj.*
FROM   dbo.Users AS u --RowStore
JOIN   dbo.MultiStatementTVF_Join(0) AS mj
ON mj.UserId = u.Id
WHERE  u.LastAccessDate >= '2016-12-01';

這些查詢每個都連接到不同的表。一個列儲存,一個沒有。他們都獲得了交錯執行計劃。

堅果

交錯執行何時起作用?

目前,它僅適用於關聯在函式之外完成的 MSTVF 。

這裡有幾個例子:

此函式沒有內部相關性,這意味著沒有WHERE基於表列和傳入變數的子句。

CREATE OR ALTER FUNCTION dbo.MultiStatementTVF_Join
(
   @h BIGINT
)
RETURNS @Out TABLE
(
   UserId INT,
   BadgeCount BIGINT
)
AS
   BEGIN
       INSERT INTO @Out ( UserId, BadgeCount )
       SELECT   b.UserId, COUNT_BIG(*) AS BadgeCount
       FROM     dbo.Badges AS b
       GROUP BY b.UserId
       HAVING   COUNT_BIG(*) > @h;
       RETURN;
   END;
GO

這個函式是相反的,在UserId帶有傳入變數的列上使用謂詞。

CREATE OR ALTER FUNCTION dbo.MultiStatementTVF_CrossApply
(
   @h BIGINT,
   @id INT
)
RETURNS @Out TABLE
(
   UserId INT,
   BadgeCount BIGINT
)
AS
   BEGIN
       INSERT INTO @Out ( UserId, BadgeCount )
       SELECT   b.UserId, COUNT_BIG(*) AS BadgeCount
       FROM     dbo.Badges AS b
       WHERE    b.UserId = @id
       GROUP BY b.UserId
       HAVING   COUNT_BIG(*) > @h;
       RETURN;
   END;
GO

這是一個常見的誤解,CROSS APPLY不會奏效。真正的限制是前面提到的。內部功能相關性是交易破壞者。

SELECT u.Id, mj.*
FROM   dbo.Users AS u --RowStore
CROSS APPLY dbo.MultiStatementTVF_Join(0) AS mj
WHERE  mj.UserId = u.Id
      AND u.LastAccessDate >= '2016-12-01';


SELECT   TOP 1 u.Id, mj.*
FROM     dbo.Users AS u --RowStore
CROSS APPLY dbo.MultiStatementTVF_CrossApply(2147483647, u.Id) AS mj
WHERE    u.LastAccessDate >= '2016-12-01'
ORDER BY u.Id;

堅果

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