Apakah ini bug dengan SQL Server 2016?
Iya. Jelas ini bukan perilaku yang benar. Saya telah melaporkannya di sini dan diperbaiki di SQL Server 2016 SP2 CU9 .
Seperti yang dikatakan Mikael Eriksson dalam komentar sys.database_scoped_configurations
dan sys.dm_exec_sessions
diimplementasikan sebagai tampilan dalam format
SELECT ...
FROM OpenRowset(TABLE xxxx)
Namun membandingkan dua rencana di bawah ini ada perbedaan yang jelas.
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 );
Lacak flag 8619 output untuk kedua queri ini
Terapkan Aturan: EnforceHPandAccCard - x0-> Spool atau Top (x0)
SQL Server tampaknya tidak dapat memastikan bahwa sumber untuk TVF tidak juga target penyisipan sehingga membutuhkan perlindungan Halloween.
Dalam kasus sesi ini diimplementasikan sebagai gulungan yang menangkap semua baris terlebih dahulu. Di database_scoped_configurations
dengan menambahkan TOP 1
ke rencana. Penggunaan TOP
untuk perlindungan Halloween dibahas dalam artikel ini . Artikel itu juga menyebutkan bendera jejak yang tidak berdokumen untuk memaksa spool daripada TOP
yang berfungsi seperti yang diharapkan.
DECLARE @database_scoped_configurations TABLE(x INT);
INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM sys.database_scoped_configurations
OPTION (QUERYTRACEON 8692)
Masalah yang jelas dengan menggunakan TOP 1
daripada spool adalah bahwa itu akan secara sewenang-wenang membatasi jumlah baris yang dimasukkan. Jadi ini hanya akan valid jika jumlah baris yang dikembalikan oleh fungsi adalah <= 1.
Memo awal terlihat seperti ini
Bandingkan ini dengan memo awal untuk kueri 2
Jika saya memahami hal di atas dengan benar, ia berpikir bahwa TVF pertama dapat mengembalikan maksimum satu baris dan menerapkan pengoptimalan yang salah. Maks untuk kueri kedua diatur ke 1.34078E+154
( 2^512
).
Saya tidak tahu dari mana asal jumlah baris maksimum ini. Mungkin metadata disediakan oleh penulis DMV? Juga aneh bahwa TOP(50)
penyelesaiannya tidak ditulis ulang TOP(1)
karena TOP(50)
tidak akan mencegah masalah Halloween terjadi (meskipun akan menghentikannya berlanjut tanpa batas waktu)