这是SQL Server 2016的错误吗?
是。绝对这不是正确的行为。我在这里报告了该问题,并已在SQL Server 2016 SP2 CU9中修复。
正如Mikael Eriksson在评论中所说,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)
这不会阻止万圣节问题的发生(尽管会无限期地阻止它继续下去)