Isso é um erro do SQL Server 2016?
Sim. Definitivamente, este não é um comportamento correto. Eu relatei aqui e foi corrigido no SQL Server 2016 SP2 CU9 .
Como Mikael Eriksson diz nos comentários sys.database_scoped_configurations
e sys.dm_exec_sessions
são implementados como visualizações no formato
SELECT ...
FROM OpenRowset(TABLE xxxx)
No entanto, comparando os dois planos abaixo, há uma diferença óbvia.
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 );
A saída do sinalizador de rastreamento 8619 para ambas as consultas mostra
Aplicar regra: EnforceHPandAccCard - x0-> spool ou superior (x0)
Aparentemente, o SQL Server não é capaz de verificar se a fonte do TVF também não é o destino da inserção, portanto, requer proteção de Halloween.
No caso das sessões, isso foi implementado como um spool que captura todas as linhas primeiro. No database_scoped_configurations
adicionando um TOP 1
ao plano. O uso da TOP
proteção de Halloween é discutido neste artigo . O artigo também menciona um sinalizador de rastreamento não documentado para forçar um spool em vez de TOP
funcionar conforme o esperado.
DECLARE @database_scoped_configurations TABLE(x INT);
INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM sys.database_scoped_configurations
OPTION (QUERYTRACEON 8692)
Um problema óbvio com o uso em TOP 1
vez de um spool é que ele arbitrariamente limitará o número de linhas inseridas. Portanto, isso só seria válido se o número de linhas retornadas pela função fosse <= 1.
A nota inicial se parece com isso
Compare isso com o memorando inicial da consulta 2
Se entendi o que foi dito corretamente, ele acha que o primeiro TVF pode retornar no máximo uma linha e, portanto, aplica uma otimização incorreta. O máximo para a segunda consulta está definido como 1.34078E+154
( 2^512
).
Não faço ideia de onde esse número máximo de linhas é derivado. Talvez os metadados fornecidos pelo autor do DMV? Também é estranho que a TOP(50)
solução alternativa não seja reescrita TOP(1)
porque TOP(50)
não impediria a ocorrência do problema do Dia das Bruxas (mas impediria que continuasse indefinidamente)