Tại sao truy vấn con sử dụng song song và tham gia không?


16

Tại sao máy chủ SQL sử dụng song song khi chạy truy vấn này sử dụng truy vấn con nhưng không khi sử dụng phép nối? Phiên bản tham gia chạy nối tiếp và mất khoảng 30 lần để hoàn thành.

Tham gia phiên bản: ~ 30 giây

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

Phiên bản truy vấn con: <1 giây

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

EDIT: Xml phiên bản kế hoạch truy vấn:

Phiên bản THAM GIA

Phiên bản

Câu trả lời:


12

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 locationtestrunsrất khác nhau giữa hai kế hoạch.

Tham gia kế hoạch dự toán: 1

Kế hoạch 1

Ước tính kế hoạch truy vấn phụ: 8,748

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

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 locationvà 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,748cá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 locationschỉ 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' ) 

Nếu một ràng buộc duy nhất được thêm vào vị trí thì rõ ràng "=" sẽ trả về đúng một hàng. Sau đó, trong ví dụ của bạn, các gói truy vấn trở nên giống hệt nhau (quét -> tìm kiếm): thay đổi bảng Vị trí thêm ràng buộc U_Location_Location duy nhất không tách rời (Vị trí);
crokusek

@crokusek vâng. Nhận ra ý của bạn sau đó và xóa bình luận của tôi! Điều đó có làm tăng số lượng hàng ước tính cho phiên bản tham gia giống với truy vấn con không? Không có trên PC tại thời điểm này để kiểm tra?
Martin Smith

@crokusek Yep. trông giống như các hàng ước tính ngoài tham gia như đối với truy vấn phụ trong trường hợp đơn lẻ đó.
Martin Smith

Đúng. Kế hoạch truy vấn giống hệt nhau, cả hai ước tính 8748, cả hai thực tế 14276. Btw, tôi nghĩ rằng tiền điện toán locationId sẽ giải quyết sự khác biệt đó nhưng thực tế không phải vậy.
crokusek

1
@crokusek - Tôi cũng sẽ thêm các ràng buộc duy nhất cho vị trí và các địa điểm tương tự khác trong DB của tôi. Tôi phải thừa nhận tôi đã không nhận ra nó ảnh hưởng đến tối ưu hóa truy vấn. Tôi nghĩ rằng nó chỉ để đảm bảo tính toàn vẹn dữ liệu. Cảm ơn cho đầu vào của bạn về câu hỏi này.
Chris L
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.