Đây có phải là một lỗi với SQL Server 2016 không?
Đúng. Chắc chắn đây không phải là hành vi đúng. Tôi đã báo cáo nó ở đây và được sửa trong SQL Server 2016 SP2 CU9 .
Như Mikael Eriksson nói trong các bình luận sys.database_scoped_configurations
và sys.dm_exec_sessions
được thực hiện dưới dạng các khung nhìn ở định dạng
SELECT ...
FROM OpenRowset(TABLE xxxx)
Tuy nhiên, so sánh hai kế hoạch dưới đây có một sự khác biệt rõ ràng.
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 );
Trace cờ 8619 đầu ra cho cả hai truy vấn này cho thấy
Áp dụng quy tắc: EnforceHPandAccCard - x0-> Spool hoặc Top (x0)
SQL Server rõ ràng là không thể xác định được rằng nguồn cho TVF không phải là mục tiêu chèn nên nó yêu cầu bảo vệ Halloween.
Trong các phiên, trường hợp này được thực hiện như một ống chỉ chụp tất cả các hàng trước. Trong database_scoped_configurations
bằng cách thêm một TOP 1
vào kế hoạch. Việc sử dụng TOP
để bảo vệ Halloween được thảo luận trong bài viết này . Bài báo cũng đề cập đến một cờ theo dõi không có giấy tờ để buộc một ống chỉ hơn TOP
là hoạt động như mong đợi.
DECLARE @database_scoped_configurations TABLE(x INT);
INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM sys.database_scoped_configurations
OPTION (QUERYTRACEON 8692)
Một vấn đề rõ ràng với việc sử dụng TOP 1
chứ không phải là một ống chỉ là nó sẽ tùy ý giới hạn số lượng hàng được chèn. Vì vậy, điều này sẽ chỉ hợp lệ nếu số lượng hàng được hàm trả về là <= 1.
Bản ghi nhớ ban đầu trông như thế này
So sánh điều này với bản ghi nhớ ban đầu cho truy vấn 2
Nếu tôi hiểu chính xác những điều trên, nó nghĩ rằng TVF đầu tiên có thể trả về tối đa một hàng và do đó áp dụng tối ưu hóa không chính xác. Max cho truy vấn thứ hai được đặt thành 1.34078E+154
( 2^512
).
Tôi không biết số lượng hàng tối đa này được lấy từ đâu. Có lẽ siêu dữ liệu được cung cấp bởi tác giả của DMV? Một điều kỳ lạ là TOP(50)
cách giải quyết không được viết lại TOP(1)
bởi vì TOP(50)
sẽ không ngăn chặn sự cố Halloween xảy ra (mặc dù điều đó sẽ ngăn chặn nó tiếp diễn vô thời hạn)