Tại sao biến bảng buộc phải quét chỉ mục trong khi bảng tạm thời sử dụng tìm kiếm và tra cứu dấu trang?


18

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:

nhập mô tả hình ảnh ở đây

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:

nhập mô tả hình ảnh ở đây

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.

Câu đố SQL

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)

Câu trả lời:


15

Lý do cho hành vi là SQL Server không thể xác định có bao nhiêu hàng sẽ khớp với ForeignKey, vì không có chỉ mục nào với RowKey là cột hàng đầu (có thể suy ra điều này từ thống kê trên bảng #temp, nhưng những hàng này không tồn tại cho các biến bảng / UDTT), do đó, nó ước tính 100.000 hàng, được xử lý tốt hơn khi quét hơn là tìm kiếm + tra cứu. Vào thời điểm SQL Server nhận ra chỉ có một hàng, thì đã quá muộn.

Bạn có thể xây dựng UDTT khác nhau; trong các phiên bản SQL Server hiện đại hơn, bạn có thể tạo các chỉ mục phụ trên các biến của bảng, nhưng cú pháp này không có sẵn trong 2008 R2.

BTW bạn có thể có hành vi tìm kiếm (ít nhất là trong các thử nghiệm giới hạn của tôi) nếu bạn cố gắng tránh bitmap / thăm dò bằng cách gợi ý một vòng lặp lồng nhau tham gia:

DECLARE @Keys TABLE (RowKey INT PRIMARY KEY); -- can't hurt

INSERT @Keys (RowKey) VALUES (10);

SELECT 
     t.RowKey
    ,t.SecondColumn
FROM
    dbo.Test t 
INNER JOIN 
    @Keys k
ON
    t.ForeignKey = k.RowKey
    OPTION (LOOP JOIN);

Tôi đã học được mẹo này từ Paul White vài năm trước. Tất nhiên, bạn nên cẩn thận về việc đưa bất kỳ loại gợi ý tham gia nào vào mã sản xuất - điều này có thể thất bại nếu mọi người thay đổi đối tượng cơ bản và loại tham gia cụ thể đó không còn có thể hoặc không còn tối ưu nhất.

Đối với các truy vấn phức tạp hơn và khi bạn chuyển sang SQL Server 2012 trở lên, có thể cờ theo dõi 2453 có thể giúp ích. Lá cờ đó đã không giúp với sự tham gia đơn giản này, mặc dù. Và những từ chối tương tự sẽ được áp dụng - đây chỉ là một việc thay thế mà bạn thường không nên làm nếu không có rất nhiều tài liệu và quy trình kiểm tra hồi quy nghiêm ngặt.

Ngoài ra, Gói dịch vụ 1 không còn hỗ trợ, bạn nên sử dụng Gói dịch vụ 3 + MS15-058 .


3

Các biến bảng và bảng tạm thời được xử lý khác nhau theo một số cách. Có một câu trả lời tuyệt vời ở đây với rất nhiều chi tiết cụ thể về nơi chúng khác nhau.

Cụ thể trong trường hợp của bạn, tôi đoán rằng thực tế là các bảng tạm thời có thể có các số liệu thống kê bổ sung được tạo và các kế hoạch song song trong khi các biến bảng có số liệu thống kê hạn chế hơn (không có thống kê cấp cột) và không có kế hoạch song song nào là thủ phạm của bạn.

Bạn có thể tốt hơn hết là bỏ biến bảng vào bảng tạm thời trong suốt thời gian của thủ tục được lưu trữ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.