2011-07-11 31 views
14

Hãy nói rằng bạn có một cái nhìn:Tại sao đặt một mệnh đề WHERE bên ngoài xem có hiệu suất khủng khiếp

CREATE VIEW dbo.v_SomeJoinedTables AS 
SELECT 
    a.date, 
    a.Col1, 
    b.Col2, 
    DENSE_RANK() 
     OVER(PARTITION BY a.date, a.Col2 ORDER BY a.Col3) as Something 
FROM a JOIN b on a.date = b.date 

tôi đã tìm thấy rằng hiệu suất của:

SELECT * 
FROM v_SomeJoinedTables 
WHERE date > '2011-01-01' 

là tồi tệ hơn nhiều so với

SELECT *, 
    DENSE_RANK() 
    OVER(PARTITION BY a.date, a.Col2 ORDER BY a.Col3) as Something 
FROM a JOIN b ON a.date = b.date 
WHERE a.date > '2011-01-01' 

Tôi rất ngạc nhiên khi kế hoạch truy vấn cho hai câu lệnh này không giống nhau.

Tôi cũng đã thử sử dụng hàm nội tuyến có giá trị, nhưng truy vấn vẫn mất 100-1000 lần dài hơn mã tôi sao chép và dán logic chế độ xem.

Bất kỳ ý tưởng nào?

+2

Vâng, kế hoạch truy vấn trông như thế nào? Bạn có thiếu chỉ mục không? Chế độ xem có trả lại quá nhiều hàng không? Nếu mệnh đề where được áp dụng ở vị trí sai? –

+1

Chế độ xem của bạn có đang được gọi là chế độ xem không? – HLGEM

+0

Điều gì xảy ra nếu chế độ xem của bạn không chứa chức năng cửa sổ? Kết quả ngữ nghĩa dự kiến ​​của một VIEW tính toán thứ hạng trên toàn bộ tập hợp là gì, nhưng truy vấn cho chế độ xem sẽ thêm điều kiện mới - liệu RANK insde có được áp dụng trước hoặc sau điều kiện bên ngoài không? – ErikE

Trả lời

15

Được gọi là "Predicate pushing" còn gọi là lọc chậm.

Máy chủ SQL không phải lúc nào cũng nhận ra WHERE có thể được áp dụng "trước đó", bên trong chế độ xem có hiệu quả.

Nó đã được giảm nhẹ trong SQL Server 2008 để hoạt động nhiều hơn như mong đợi

+0

Đẹp tham khảo. Điều đó thực sự đáng sợ. Nó xác nhận sự nghi ngờ của tôi rằng SQL Server chưa bao giờ cảm thấy thoải mái với khái niệm về một từ khóa TOP trong SQL. Một thực sự không cần phải biết công cụ này để viết các truy vấn tối ưu hóa. – dkretz

+0

Tôi đã hoàn toàn ngạc nhiên khi biết SQL Server 2005 xử lý các hàm RANK kém đến mức nào. Có thực sự phải là một hotfix cho rằng và không yêu cầu nâng cấp lên SQL 2008. – bpeikes

+0

@ bpeikes: yep, xem http://stackoverflow.com/q/4230838/27535 và bình luận ở đây quá: http://stackoverflow.com/q/2798094/27535 – gbn

2

Tôi không phải là chuyên gia SQL, vì vậy tôi có thể bị bỏ phiếu vì sự ngu ngốc của mình, nhưng tôi đoán là trong trường hợp đầu tiên, SQL sẽ tìm nạp kết quả của chế độ xem toàn bộ chế độ xem trước khi áp dụng vị từ trong mệnh đề WHERE . Vì vậy, khi bạn truy vấn xem, nó sẽ chọn tất cả các bản ghi, đặt chúng vào bộ nhớ, và sau đó áp dụng bộ lọc Ngày sau khi nó được thực hiện.

Điều này có vẻ tương tự như cách toàn bộ tập dữ liệu được chỉ định trong kết nối của bạn được tìm nạp trước khi áp dụng bộ lọc trong WHERE (bài học ở đây là bạn nên áp dụng các biến vị ngữ trong mệnh đề ON của bạn khi có thể).

Trừ khi các chế độ xem được xử lý khác nhau bằng cách nào đó.

+0

+1 Tôi nghĩ bạn hoàn toàn đúng. Có thể số liệu thống kê bị tắt và bạn phải xác minh bằng cách so sánh các kế hoạch ước tính/thực tế cho mỗi truy vấn, nhưng có khả năng truy vấn từ chế độ xem sẽ thực hiện toàn bộ kết nối trước khi áp dụng bộ lọc, trong khi truy vấn bên ngoài có thể sử dụng bộ lọc chọn loại kết nối hiệu quả hơn nếu nó có thể loại bỏ các hàng từ một bên của kết nối trước đó. –

+0

Chế độ xem chỉ là viết tắt cho biểu thức đầy đủ. Họ sẽ không được sử dụng nhiều nếu họ không được tối ưu hóa như nhau. – dkretz

+0

+1 bạn là chính xác, câu trả lời của tôi cho thấy * tại sao * – gbn

-1

Làm việc xung quanh, tôi sẽ đề xuất sử dụng hàm thay vì chế độ xem để bạn có thể chuyển vào tham số dữ liệu.

1

Về mặt kỹ thuật, bạn không so sánh giữa các câu lệnh SQL giống nhau. Chế độ xem của bạn cho biết rằng nó trả về a.date, a.Col1, b.Col2, cộng với hàm DENSE_RANK() của bạn. Trong truy vấn của bạn không có chế độ xem, bạn trả về tất cả các cột.

Lúc đầu, bạn có thể nghĩ rằng trả về tất cả các cột sẽ tệ hơn. Nhưng thật khó để xác định cái nào sẽ tốt hơn nếu không biết cấu trúc bảng, bao gồm các chỉ mục, trông như thế nào.

Bạn đã so sánh các kế hoạch truy vấn cho từng câu sao?

+0

Hầu như hợp lệ ... chế độ xem chậm hơn, đây là điểm của câu hỏi. Ngay cả khi truy vấn nội tuyến bị "khuyết tật" bởi SELECT * – gbn

2

cú pháp OVER() là thương hiệu mới trong SS2005 và dường như không được tích hợp tốt vào trình tối ưu hóa. Tôi đề nghị bạn thử một biểu thức truyền thống hơn? Có lẽ KHÔNG phải là một biểu thức nếu bạn quan tâm đến khả năng tối ưu hóa.

http://www.sqlteam.com/article/sql-sever-2005-using-over-with-aggregate-functions

Hoặc, tốt hơn, nhận được một chút quen thuộc hơn với các hồ sơ - quan điểm nên có thể cứu vãn được.

+0

FYI, liên kết của tôi chứng tỏ điều này đã được giải quyết. Xem này quá (bình luận quá) http://stackoverflow.com/q/2798094/27535 – gbn

+0

Có lẽ, nhưng có lẽ không phải với trang web/phiên bản của mình. Nó không phải là tuyệt vời khi thực hiện như vậy là tinh ranh mà bạn cần phải biết tất cả mọi thứ bạn hoặc tôi biết để làm việc đáng tin cậy. – dkretz

+0

Thật vậy. Và dân gian như bạn hoặc tôi có xu hướng không sử dụng quan điểm như vậy sẽ không nhìn thấy nó ngày này sang ngày khác ... – gbn

Các vấn đề liên quan