Est-ce un bogue avec SQL Server 2016?
Oui. Ce n'est certainement pas un comportement correct. Je l'ai signalé ici et est résolu dans SQL Server 2016 SP2 CU9 .
Comme Mikael Eriksson le dit dans les commentaires sys.database_scoped_configurations
et sys.dm_exec_sessions
sont mis en œuvre sous forme de vues au format
SELECT ...
FROM OpenRowset(TABLE xxxx)
Cependant, en comparant les deux plans ci-dessous, il y a une différence évidente.
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 );
L'indicateur de trace 8619 affiche la sortie de ces deux requêtes
Appliquer la règle: EnforceHPandAccCard - x0-> Spool ou Top (x0)
SQL Server n'est apparemment pas en mesure de vérifier que la source du TVF n'est pas également la cible d'insertion, il nécessite donc une protection Halloween.
Dans le cas des sessions, cela a été implémenté comme un spool qui capture d'abord toutes les lignes. Dans le database_scoped_configurations
en ajoutant un TOP 1
au plan. L'utilisation de TOP
pour la protection Halloween est discutée dans cet article . L'article mentionne également un indicateur de trace non documenté pour forcer une bobine plutôt que TOP
cela fonctionne comme prévu.
DECLARE @database_scoped_configurations TABLE(x INT);
INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM sys.database_scoped_configurations
OPTION (QUERYTRACEON 8692)
Un problème évident avec l'utilisation TOP 1
plutôt qu'avec une bobine est qu'elle limitera arbitrairement le nombre de lignes insérées. Ainsi, cela ne serait valide que si le nombre de lignes renvoyées par la fonction était <= 1.
Le mémo initial ressemble à ceci
Comparez cela avec le mémo initial de la requête 2
Si je comprends bien ce qui précède, il pense que le premier TVF peut renvoyer un maximum d'une ligne et applique donc une optimisation incorrecte. Le Max pour la deuxième requête est défini sur 1.34078E+154
( 2^512
).
Je n'ai aucune idée d'où ce nombre maximal de lignes est dérivé. Peut-être des métadonnées fournies par l'auteur du DMV? Il est également étrange que la TOP(50)
solution de contournement ne soit pas réécrite, TOP(1)
car TOP(50)
cela n'empêcherait pas le problème d'Halloween de se produire (mais l'empêcherait de continuer indéfiniment)