Це помилка в SQL Server 2016?
Так. Однозначно це не правильна поведінка. Я повідомив про це тут і фіксується в SQL Server 2016 SP2 CU9 .
Як каже Мікаель Ерікссон у коментарях sys.database_scoped_configurations
і sys.dm_exec_sessions
реалізується як перегляд у форматі
SELECT ...
FROM OpenRowset(TABLE xxxx)
Однак порівняння двох планів нижче є очевидною різницею.
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.34078E+154
( 2^512
).
Я не маю уявлення, звідки походить ця максимальна кількість рядків. Можливо, метадані, надані автором DMV? Також дивно, що TOP(50)
вирішення не буде переписано, TOP(1)
оскільки TOP(50)
це не завадить виникнути проблему Хеллоуїна (хоча це не зупинить її продовження на невизначений час)