Saya sedang meneliti sesuatu yang lain ketika saya menemukan hal ini. Saya menghasilkan tabel uji dengan beberapa data di dalamnya dan menjalankan kueri yang berbeda untuk mengetahui bagaimana cara berbeda untuk menulis kueri mempengaruhi rencana eksekusi. Berikut ini skrip yang saya gunakan untuk menghasilkan data uji acak:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('t') AND type in (N'U'))
DROP TABLE t
GO
CREATE TABLE t
(
c1 int IDENTITY(1,1) NOT NULL
,c2 int NULL
)
GO
insert into t
select top 1000000 a from
(select t1.number*2048 + t2.number a, newid() b
from [master]..spt_values t1
cross join [master]..spt_values t2
where t1.[type] = 'P' and t2.[type] = 'P') a
order by b
GO
update t set c2 = null
where c2 < 2048 * 2048 / 10
GO
CREATE CLUSTERED INDEX pk ON [t] (c1)
GO
CREATE NONCLUSTERED INDEX i ON t (c2)
GO
Sekarang, mengingat data ini, saya meminta pertanyaan berikut:
select *
from t
where
c2 < 1048576
or c2 is null
;
Yang sangat mengejutkan saya, rencana eksekusi yang dihasilkan untuk permintaan ini, adalah ini . (Maaf untuk tautan eksternal, terlalu besar untuk muat di sini).
Adakah yang bisa menjelaskan kepada saya apa yang terjadi dengan semua " Pemindaian Konstan " dan " Kalkulator Komputasi " ini? Apa yang terjadi?
|--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1010], [Expr1011], [Expr1012]))
|--Merge Interval
| |--Sort(TOP 2, ORDER BY:([Expr1013] DESC, [Expr1014] ASC, [Expr1010] ASC, [Expr1015] DESC))
| |--Compute Scalar(DEFINE:([Expr1013]=((4)&[Expr1012]) = (4) AND NULL = [Expr1010], [Expr1014]=(4)&[Expr1012], [Expr1015]=(16)&[Expr1012]))
| |--Concatenation
| |--Compute Scalar(DEFINE:([Expr1005]=NULL, [Expr1006]=NULL, [Expr1004]=(60)))
| | |--Constant Scan
| |--Compute Scalar(DEFINE:([Expr1008]=NULL, [Expr1009]=(1048576), [Expr1007]=(10)))
| |--Constant Scan
|--Index Seek(OBJECT:([t].[i]), SEEK:([t].[c2] > [Expr1010] AND [t].[c2] < [Expr1011]) ORDERED FORWARD)
sumber
62
untuk perbandingan kesetaraan. Saya kira60
pasti berarti bahwa alih-alih> AND <
seperti yang ditunjukkan dalam rencana Anda sebenarnya dapatkan>= AND <=
kecuali itu adalahIS NULL
bendera eksplisit mungkin (?) Atau mungkin bit2
menunjukkan sesuatu yang lain yang tidak terkait dan60
masih sama seperti ketika saya lakukanset ansi_nulls off
dan mengubahnya untukc2 = null
itu masih tetap di60
Pemindaian konstan adalah cara untuk SQL Server untuk membuat ember di mana itu akan menempatkan sesuatu nanti dalam rencana eksekusi. Saya telah memposting penjelasan yang lebih menyeluruh di sini . Untuk memahami untuk apa pemindaian konstan, Anda harus melihat lebih jauh ke dalam rencana. Dalam kasus ini, operator Compute Scalar yang digunakan untuk mengisi ruang yang dibuat oleh pemindaian konstan.
Operator Compute Scalar sedang dimuat dengan NULL dan nilai 1045876, jadi mereka jelas akan digunakan dengan Loop Join dalam upaya untuk memfilter data.
Bagian yang sangat keren adalah bahwa rencana ini adalah Sepele. Ini berarti bahwa ia melewati proses optimasi minimal. Semua operasi mengarah ke Interval Penggabungan. Ini digunakan untuk membuat satu set minimal operator perbandingan untuk pencarian indeks ( detailnya di sini ).
Idenya adalah untuk menyingkirkan nilai yang tumpang tindih sehingga kemudian dapat menarik data dengan melewati minimal. Meskipun masih menggunakan operasi loop, Anda akan perhatikan bahwa loop dieksekusi tepat sekali, yang berarti, itu secara efektif memindai.
ADDENDUM: Kalimat terakhir tidak aktif. Ada dua upaya. Saya salah membaca rencana. Sisa konsepnya sama dan tujuannya, operan minimal, sama.
sumber