Saya mencoba memahami mengapa menggunakan variabel tabel mencegah pengoptimal menggunakan pencarian indeks dan kemudian bookmark lookup versus scan indeks.
Mengisi tabel:
CREATE TABLE dbo.Test
(
RowKey INT NOT NULL PRIMARY KEY,
SecondColumn CHAR(1) NOT NULL DEFAULT 'x',
ForeignKey INT NOT NULL
)
INSERT dbo.Test
(
RowKey,
ForeignKey
)
SELECT TOP 1000000
ROW_NUMBER() OVER (ORDER BY (SELECT 0)),
ABS(CHECKSUM(NEWID()) % 10)
FROM sys.all_objects s1
CROSS JOIN sys.all_objects s2
CREATE INDEX ix_Test_1 ON dbo.Test (ForeignKey)
Mengisi variabel tabel dengan catatan tunggal dan mencoba untuk mencari kunci utama dan kolom kedua dengan mencari di kolom kunci asing:
DECLARE @Keys TABLE (RowKey INT NOT NULL)
INSERT @Keys (RowKey) VALUES (10)
SELECT
t.RowKey,
t.SecondColumn
FROM
dbo.Test t
INNER JOIN
@Keys k
ON
t.ForeignKey = k.RowKey
Di bawah ini adalah rencana eksekusi:
Sekarang kueri yang sama menggunakan tabel temp sebagai gantinya:
CREATE TABLE #Keys (RowKey INT NOT NULL)
INSERT #Keys (RowKey) VALUES (10)
SELECT
t.RowKey,
t.SecondColumn
FROM
dbo.Test t
INNER JOIN
#Keys k
ON
t.ForeignKey = k.RowKey
Paket permintaan ini menggunakan pencarian pencarian dan penanda:
Mengapa pengoptimal bersedia melakukan pencarian bookmark dengan tabel temp, tetapi tidak variabel tabel?
Variabel tabel digunakan dalam contoh ini untuk mewakili data yang datang melalui tipe tabel yang ditentukan pengguna dalam prosedur tersimpan.
Saya menyadari pencarian indeks mungkin tidak sesuai jika nilai kunci asing terjadi ratusan ribu kali. Dalam hal ini, pemindaian mungkin akan menjadi pilihan yang lebih baik. Untuk skenario yang saya buat, tidak ada baris dengan nilai 10. Saya masih berpikir perilaku itu menarik dan ingin tahu apakah ada alasan untuk itu.
Menambahkan OPTION (RECOMPILE)
tidak mengubah perilaku. UDDT memiliki kunci utama.
@@VERSION
adalah SQL Server 2008 R2 (SP2) - 10.50.4042.0 (X64) (Build 7601: Paket Layanan 1) (Hypervisor)