Như đã chỉ ra trong các bình luận, có vẻ như bạn cần cập nhật số liệu thống kê của mình.
Số lượng hàng ước tính ra khỏi liên kết giữa location
và testruns
rất khác nhau giữa hai kế hoạch.
Tham gia kế hoạch dự toán: 1
Ước tính kế hoạch truy vấn phụ: 8,748
Số lượng hàng thực tế sắp ra khỏi tham gia là 14.276.
Tất nhiên, hoàn toàn không có ý nghĩa trực quan rằng phiên bản tham gia nên ước tính rằng 3 hàng sẽ xuất phát location
và tạo một hàng đã tham gia trong khi truy vấn phụ ước tính rằng một trong những hàng đó sẽ tạo ra 8,748 từ cùng một liên kết nhưng dù sao tôi cũng có thể để tái tạo điều này.
Điều này dường như xảy ra nếu không có sự giao thoa giữa các biểu đồ khi số liệu thống kê được tạo. Phiên bản tham gia giả định một hàng duy nhất. Và tìm kiếm đẳng thức duy nhất của truy vấn phụ giả định các hàng ước tính giống như tìm kiếm đẳng thức đối với một biến không xác định.
Cardinality của testruns là 26244
. Giả sử được điền với ba id vị trí riêng biệt thì các truy vấn sau đây ước tính rằng 8,748
các hàng sẽ được trả về ( 26244/3
)
declare @i int
SELECT *
FROM testruns AS tr
WHERE tr.location_id = @i
Cho rằng bảng locations
chỉ chứa 3 hàng, thật dễ dàng (nếu chúng ta giả sử không có khóa ngoại) để tạo ra một tình huống trong đó các số liệu thống kê được tạo và sau đó dữ liệu được thay đổi theo cách ảnh hưởng đáng kể đến số lượng hàng thực tế được trả về nhưng không đủ ngắt cập nhật tự động các số liệu thống kê và biên dịch lại ngưỡng.
Vì SQL Server nhận được số lượng hàng ra khỏi liên kết đó nên tất cả các ước tính hàng khác trong kế hoạch tham gia đều bị đánh giá thấp. Cũng như có nghĩa là bạn nhận được một kế hoạch nối tiếp, truy vấn cũng nhận được một cấp bộ nhớ không đủ và các loại và hàm băm tham gia tràn vào tempdb
.
Một kịch bản có thể tái tạo các hàng thực tế so với các hàng ước tính được hiển thị trong kế hoạch của bạn ở bên dưới.
CREATE TABLE location
(
id INT CONSTRAINT locationpk PRIMARY KEY,
location VARCHAR(MAX) /*From the separate filter think you are using max?*/
)
/*Temporary ids these will be updated later*/
INSERT INTO location
VALUES (101, 'Coventry'),
(102, 'Nottingham'),
(103, 'Derby')
CREATE TABLE testruns
(
location_id INT
)
CREATE CLUSTERED INDEX IX ON testruns(location_id)
/*Add in 26244 rows of data split over three ids*/
INSERT INTO testruns
SELECT TOP (5984) 1
FROM master..spt_values v1, master..spt_values v2
UNION ALL
SELECT TOP (5984) 2
FROM master..spt_values v1, master..spt_values v2
UNION ALL
SELECT TOP (14276) 3
FROM master..spt_values v1, master..spt_values v2
/*Create statistics. The location_id histograms don't intersect at all*/
UPDATE STATISTICS location(locationpk) WITH FULLSCAN;
UPDATE STATISTICS testruns(IX) WITH FULLSCAN;
/* UPDATE location.id. Three row update is below recompile threshold*/
UPDATE location
SET id = id - 100
Sau đó, chạy các truy vấn sau đây cho cùng một ước tính so với chênh lệch thực tế
SELECT *
FROM testruns AS tr
WHERE tr.location_id = (SELECT id
FROM location
WHERE location = 'Derby')
SELECT *
FROM testruns AS tr
JOIN location loc
ON tr.location_id = loc.id
WHERE loc.location = ( 'Derby' )