Tôi đang cố gắng hiểu tại sao sử dụng biến bảng lại ngăn trình tối ưu hóa sử dụng tìm kiếm chỉ mục và sau đó đánh dấu tra cứu so với quét chỉ mục.
Đặt bảng:
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)
Tạo một biến bảng với một bản ghi duy nhất và cố gắng tra cứu khóa chính và cột thứ hai bằng cách tìm kiếm trên cột khóa ngoại:
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
Dưới đây là kế hoạch thực hiện:
Bây giờ cùng một truy vấn sử dụng bảng tạm thời thay thế:
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
Gói truy vấn này sử dụng tra cứu tìm kiếm và đánh dấu:
Tại sao trình tối ưu hóa sẵn sàng thực hiện tra cứu dấu trang với bảng tạm thời, nhưng không phải là biến bảng?
Biến bảng được sử dụng trong ví dụ này để biểu thị dữ liệu đi qua loại bảng do người dùng xác định trong một thủ tục được lưu trữ.
Tôi nhận thấy việc tìm kiếm chỉ mục có thể không phù hợp nếu giá trị khóa ngoại xảy ra hàng trăm ngàn lần. Trong trường hợp đó, quét có thể là một lựa chọn tốt hơn. Đối với kịch bản tôi đã tạo, không có hàng nào có giá trị 10. Tôi vẫn nghĩ rằng hành vi này rất thú vị và muốn biết liệu có lý do nào cho nó không.
Thêm OPTION (RECOMPILE)
không thay đổi hành vi. UDĐT có khóa chính.
@@VERSION
là SQL Server 2008 R2 (SP2) - 10.50.4042.0 (X64) (Bản dựng 7601: Gói dịch vụ 1) (Hypervisor)