これはSQL Server 2016のバグですか?
はい。間違いなくこれは正しい行動ではありません。私はそれをここで報告し、SQL Server 2016 SP2 CU9で修正されています。
ミカエル・エリクソンは、コメントで言うsys.database_scoped_configurations
とsys.dm_exec_sessions
形式のビューとして実装されています
SELECT ...
FROM OpenRowset(TABLE xxxx)
ただし、以下の2つのプランを比較すると明らかな違いがあります。
DBCC TRACEON(3604);
DECLARE @database_scoped_configurations TABLE(x INT);
INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM sys.database_scoped_configurations
OPTION (QUERYTRACEON 8608, QUERYTRACEON 8615, QUERYTRACEON 8619, QUERYTRACEON 8620 );
DECLARE @dm_exec_sessions TABLE(x INT);
INSERT INTO @dm_exec_sessions
SELECT session_id
FROM sys.dm_exec_sessions
OPTION (QUERYTRACEON 8608, QUERYTRACEON 8615, QUERYTRACEON 8619, QUERYTRACEON 8620 );
これらのクエリの両方のトレースフラグ8619の出力が示す
ルールの適用:EnforceHPandAccCard-x0->スプールまたはトップ(x0)
SQL Serverは、TVFのソースが挿入ターゲットでもないことを確認できないため、ハロウィーン保護が必要です。
セッションの場合、これは最初にすべての行をキャプチャするスプールとして実装されました。database_scoped_configurations
追加することにより、TOP 1
計画に。TOP
ハロウィーン保護のためのの使用については、この記事で説明します。記事には、ドキュメントに記載されていないトレースフラグについても言及TOP
されています。
DECLARE @database_scoped_configurations TABLE(x INT);
INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM sys.database_scoped_configurations
OPTION (QUERYTRACEON 8692)
TOP 1
スプールではなく使用の明らかな問題は、挿入される行数を任意に制限することです。したがって、これは、関数によって返された行数が<= 1の場合にのみ有効です。
最初のメモはこんな感じ
これをクエリ2の最初のメモと比較してください
上記を正しく理解している場合、最初のTVFは最大で1行を返すことができるため、不適切な最適化が適用されます。2番目のクエリの最大値は1.34078E+154
(2^512
)に設定されます。
この最大行数がどこから派生するのか私にはわかりません。おそらく、DMVの作成者によって提供されたメタデータですか?ハロウィーンの問題の発生を防ぐことができないため、TOP(50)
回避策が書き直されないことも奇妙です(無期限に継続するのを止めます)TOP(1)
TOP(50)