Interleaved Executionは、2017年のクエリプロセッサの 機能のファミリ の一部であり、以下で構成されています。
では、インターリーブ実行はどのように機能するのでしょうか。
悪魔はテーブル変数にあります
インターリーブ実行は、マルチステートメントテーブル値関数で誤推定された正しいカーディナリティを目的としています。
SQL Serverの以前のバージョンでは、これらの関数は常にお粗末な見積もりを作成していました。
言うまでもなく、これは他のテーブルに結合するときに多くの問題を引き起こす可能性があります。
テーブル変数からデータを選択しても、それ自体で並列処理が妨げられることはありませんが、行推定値が低いと、クエリのコストが低くなり、並列処理が考慮されません。
Interleaved Executionを使用すると、カーディナリティの推定が一時停止され、MSTVFのサブツリーが実行され、より正確なカーディナリティの推定で最適化が再開されます。
MSTVFがインターリーブされた実行を受信するかどうかを知る方法
アダプティブ結合と同様に、インターリーブ実行はクエリプランに記述されます。アダプティブ結合とは異なり、少なくともこの記事の執筆時点では、推定計画には記載されていません。
Interleaved Executionを使用したMSTVFのプラン形状は、MSTVFが含まれている一般的なプランとは少し異なります。
プランの上部にテーブル値関数演算子と、TVFオペレーターが通常はグラフィカルプランにあるテーブル変数のスキャンが表示されます。
TVF演算子の上にカーソルを合わせると、属性IsInterleavedExecuted
がTrueに設定されていることと、現実をほとんど反映していると推定される行数が表示されます。フラー。
インターリーブ実行が発生しない場合にトラブルシューティングする拡張イベントはありますか?
はい、たくさんあります:
これらの一部はデバッグチャネルにあり、拡張するイベントを検索するときにデフォルトで選択されていないことに注意してください。
インターリーブされたExectionにはColumnStoreインデックスが必要ですか?
いいえ、どちらの方法でも機能します。次に例を示します。
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';
これらのクエリはそれぞれ異なるテーブルに結合します。 1つのColumnStore、1つではありません。どちらもInterleaved Executionプランを取得します。
インターリーブ実行はいつ機能しますか?
現在、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;