Tại sao truy vấn này không sử dụng bộ đệm chỉ mục?


23

Tôi đang hỏi câu hỏi này để hiểu rõ hơn về hành vi của trình tối ưu hóa và để hiểu các giới hạn xung quanh các cuộn chỉ số. Giả sử tôi đặt các số nguyên từ 1 đến 10000 thành một đống:

CREATE TABLE X_10000 (ID INT NOT NULL);
truncate table X_10000;

INSERT INTO X_10000 WITH (TABLOCK)
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

Và buộc một vòng lặp lồng nhau tham gia với MAXDOP 1:

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);

Đây là một hành động khá không thân thiện đối với SQL Server. Các vòng lặp lồng nhau thường không phải là một lựa chọn tốt khi cả hai bảng không có bất kỳ chỉ mục liên quan nào. Đây là kế hoạch:

truy vấn xấu

Truy vấn mất 13 giây trên máy của tôi với 100000000 hàng được tìm nạp từ bộ đệm bảng. Tuy nhiên, tôi không thấy lý do tại sao truy vấn phải chậm. Trình tối ưu hóa truy vấn có khả năng tạo các chỉ mục một cách nhanh chóng thông qua các cuộn chỉ mục . Truy vấn này có vẻ như là một ứng cử viên hoàn hảo cho một bộ đệm chỉ mục.

Truy vấn sau đây trả về kết quả giống như truy vấn đầu tiên, có bộ đệm chỉ mục và kết thúc sau chưa đầy một giây:

SELECT *
FROM X_10000 a
CROSS APPLY (SELECT TOP (9223372036854775807) b.ID FROM X_10000 b WHERE a.ID = b.ID) ca
OPTION (LOOP JOIN, MAXDOP 1);

cách giải quyết 1

Truy vấn này cũng có một bộ đệm chỉ mục và kết thúc sau chưa đầy một giây:

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID >= b.ID AND a.ID <= b.ID
OPTION (LOOP JOIN, MAXDOP 1);

cách giải quyết 2

Tại sao truy vấn ban đầu không có bộ đệm chỉ mục? Có bất kỳ tập hợp các gợi ý tài liệu hoặc không có giấy tờ hoặc cờ theo dõi sẽ cung cấp cho nó một bộ chỉ mục không? Tôi đã tìm thấy câu hỏi liên quan này , nhưng nó không trả lời đầy đủ câu hỏi của tôi và tôi không thể làm cho cờ theo dõi bí ẩn hoạt động cho truy vấn này.

Câu trả lời:


20

Như bạn đã biết, tìm kiếm của trình tối ưu hóa không đầy đủ. Nó thử những thứ có ý nghĩa trong ngữ cảnh và thường trả cổ tức cho các truy vấn thực sự. Việc buộc một phép nối vòng lặp giữa hai bảng heap không có cột đơn không phải là một kịch bản như vậy. Điều đó nói rằng, đây là một số chi tiết:

SQL Server thích chuyển đổi áp dụng để tham gia sớm, bởi vì nó biết nhiều thủ thuật hơn với các phép nối. Sau đó, nó có thể khám phá chuyển đổi tham gia trở lại để áp dụng. Sự khác biệt giữa hai tham số tương quan (tham chiếu bên ngoài). Áp dụng có ý nghĩa khi có một chỉ số phù hợp ở phía bên trong. Ví dụ của bạn không có chỉ mục, vì vậy trình tối ưu hóa không bị thuyết phục để khám phá bản dịch sang ứng dụng.

Phép nối đơn giản (không áp dụng) có biến vị ngữ nối trên toán tử nối thay vì tham chiếu ngoài. Tối ưu hóa bộ đệm cho không áp dụng thường là một bộ đệm bảng lười biếng, vì không có vị ngữ ở phía bên trong, chỉ có ở phần nối.

Trình tối ưu hóa không xem xét việc xây dựng một chỉ mục một cách nhanh chóng để cho phép áp dụng; thay vì chuỗi các sự kiện thường là ngược lại: biến đổi để áp dụng vì tồn tại một chỉ số tốt.

Đôi khi bạn có thể khuyến khích áp dụng thay vì tham gia bằng cách sử dụng APPLYcú pháp trong truy vấn của bạn. Cờ theo dõi không có giấy tờ 9114 có thể hỗ trợ trong việc này bằng cách ngăn cản trình tối ưu hóa dịch một ứng dụng logic sang một mặt trước nối lên. Ví dụ:

SELECT * 
FROM dbo.X_1000 AS a
CROSS APPLY (SELECT * FROM dbo.X_1000 AS b WHERE b.ID = a.ID) AS b
OPTION (QUERYTRACEON 9114);

Kế hoạch ống chỉ

Một bộ đệm chỉ mục được ưa thích để áp dụng vì tham chiếu bên ngoài có nghĩa là lựa chọn được áp dụng ở phía bên trong của phép nối. Bạn sẽ thường thấy điều này thông qua SelToIndexOnTheFlynhưng các đường dẫn khác tồn tại. Xem bài viết của tôi The Spager Index Spool và Trình tối ưu hóa .

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.