¿Es esto un error con SQL Server 2016?
Si. Definitivamente este no es el comportamiento correcto. Lo informé aquí y se solucionó en SQL Server 2016 SP2 CU9 .
Como dice Mikael Eriksson en los comentarios sys.database_scoped_configurations
y sys.dm_exec_sessions
se implementan como vistas en el formato
SELECT ...
FROM OpenRowset(TABLE xxxx)
Sin embargo, al comparar los dos planes a continuación, hay una diferencia obvia.
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 );
La salida del indicador de rastreo 8619 para ambas consultas muestra
Aplicar regla: EnforceHPandAccCard - x0-> Spool or Top (x0)
SQL Server aparentemente no puede determinar que la fuente del TVF no sea también el objetivo de inserción, por lo que requiere protección de Halloween.
En el caso de las sesiones, esto se implementó como un carrete que captura todas las filas primero. En el database_scoped_configurations
mediante la adición de un TOP 1
al plan. El uso de TOP
para la protección de Halloween se trata en este artículo . El artículo también menciona una marca de rastreo indocumentada para forzar un carrete en lugar de TOP
que funcione como se esperaba.
DECLARE @database_scoped_configurations TABLE(x INT);
INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM sys.database_scoped_configurations
OPTION (QUERYTRACEON 8692)
Un problema obvio con el uso en TOP 1
lugar de un carrete es que limitará arbitrariamente el número de filas insertadas. Por lo tanto, esto solo sería válido si el número de filas devueltas por la función fuera <= 1.
El memo inicial se ve así
Compare esto con la nota inicial para la consulta 2
Si entiendo correctamente lo anterior, creo que el primer TVF puede devolver un máximo de una fila y, por lo tanto, aplica una optimización incorrecta. El valor máximo para la segunda consulta se establece en 1.34078E+154
( 2^512
).
No tengo idea de dónde se deriva este recuento de filas máximo. ¿Quizás los metadatos proporcionados por el autor del DMV? También es extraño que la TOP(50)
solución no se vuelva a escribir TOP(1)
porque TOP(50)
no evitaría que ocurriera el problema de Halloween (aunque evitaría que continuara indefinidamente)