È un bug con SQL Server 2016?
Sì. Sicuramente questo non è un comportamento corretto. L'ho segnalato qui ed è stato risolto in SQL Server 2016 SP2 CU9 .
Come dice Mikael Eriksson nei commenti sys.database_scoped_configurations
e sys.dm_exec_sessions
sono implementati come viste nel formato
SELECT ...
FROM OpenRowset(TABLE xxxx)
Tuttavia, confrontando i due piani seguenti c'è un'ovvia differenza.
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 );
Traccia flag 8619 output per entrambi questi spettacoli di query
Applica regola: EnforceHPandAccCard - x0-> Spool o Top (x0)
Apparentemente SQL Server non è in grado di accertare che l'origine per TVF non sia anche la destinazione di inserimento, quindi richiede la protezione di Halloween.
Nel caso delle sessioni questo è stato implementato come spool che cattura prima tutte le righe. Nel database_scoped_configurations
aggiungendo un TOP 1
al piano. L'uso di TOP
per la protezione di Halloween è discusso in questo articolo . L'articolo menziona anche un flag di traccia non documentato per forzare una bobina piuttosto TOP
che funziona come previsto.
DECLARE @database_scoped_configurations TABLE(x INT);
INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM sys.database_scoped_configurations
OPTION (QUERYTRACEON 8692)
Un ovvio problema nell'uso TOP 1
piuttosto che in uno spool è che limiterà arbitrariamente il numero di righe inserite. Pertanto, ciò sarebbe valido solo se il numero di righe restituite dalla funzione fosse <= 1.
Il promemoria iniziale è simile al seguente
Confronta questo con il promemoria iniziale per la query 2
Se capisco correttamente quanto sopra, pensa che il primo TVF possa restituire un massimo di una riga e quindi applica un'ottimizzazione errata. Il valore massimo per la seconda query è impostato su 1.34078E+154
( 2^512
).
Non ho idea da dove derivi questo conteggio delle righe massimo. Forse i metadati forniti dall'autore del DMV? È anche strano che la TOP(50)
soluzione alternativa non venga riscritta TOP(1)
perché TOP(50)
non impedirebbe il verificarsi del problema di Halloween (anche se impedirebbe che continui indefinitamente)