Kế hoạch thực hiện tốt hơn nếu tham số được lưu trữ trong biến cục bộ


8

Tôi có hai thủ tục lưu trữ. Cái này cực nhanh (~ 2 giây)

CREATE PROCEDURE [schema].[Test_fast]
   @week date
AS
BEGIN

    declare @myweek date = @week

    select distinct serial 
    from [schema].[tEventlog]         as e
    join [schema].tEventlogSourceName as s on s.ID = e.FKSourceName
    where s.SourceName = 'source_name'
        and (e.EventCode = 1 or e.EventCode = 9)
        and cast(@myweek as datetime2(3)) <= [Date] 
        and [Date] < dateadd(day, 7, cast(@myweek as datetime2(3)))    
END

Và cái này chạy chậm (~ 2 giờ):

create PROCEDURE [schema].[Test_slow]
   @week date
AS
BEGIN

    select distinct serial 
    from [schema].[tEventlog]         as e
    join [schema].tEventlogSourceName as s on s.ID = e.FKSourceName
    where s.SourceName = 'source_name'
        and (e.EventCode = 1 or e.EventCode = 9)
        and cast(@week as datetime2(3)) <= [Date] 
        and [Date] < dateadd(day, 7, cast(@week as datetime2(3)))
END

Sự khác biệt thực sự duy nhất là dòng (sử dụng biến cục bộ @myweek):

declare @myweek date = @week

Dưới đây là các kế hoạch thực hiện. Kế hoạch đầu tiên là từ [lược đồ]. [Test_fast] và kế hoạch thứ hai là từ [lược đồ]. [Test_slow]:

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

Câu hỏi của tôi là: Tại sao SQL Server 2012 có kế hoạch thực hiện tốt hơn (nhanh hơn) khi tôi lấy tham số và lưu trữ nó trong một biến cục bộ, sau đó sử dụng biến cục bộ này. Có một cái gì đó bị phá vỡ với các số liệu thống kê hoặc các chỉ số? (Tôi cũng tự hỏi tại sao kế hoạch thực hiện thứ hai không sử dụng bất kỳ loại thực thi song song nào).

CẬP NHẬT :

Tôi cung cấp cho 2 SP cùng một Thông số và khởi động chúng cùng một lúc (gần 2 giây khác nhau) không phải là cập nhật tự động thống kê trong DB này.

thí dụ:

EXEC    [schema].[Test_fast]
        @week = '2016-02-08'

EXEC    [schema].[Test_slow]
        @week = '2016-02-08'

Đây là Kế hoạch thực hiện:

https://gist.github.com/anonymous/6e404f896d9613c2061a#file-sp_execut_plan-sqlplan

Một bản cập nhật bổ sung của chỉ số cũng không có hiệu lực.

Câu trả lời:


16

Sử dụng các biến cục bộ ngăn chặn việc đánh hơi các giá trị tham số, do đó các truy vấn được biên dịch dựa trên thống kê phân phối trung bình . Đây là cách giải quyết cho một số loại vấn đề độ nhạy tham số trước đó OPTION (OPTIMIZE FOR UNKNOWN)cờ theo dõi 4136 đã có sẵn.

Từ kế hoạch thực hiện được cung cấp, đây chính xác là những gì đã xảy ra trong trường hợp của bạn.

Khi một biến cục bộ được sử dụng, giá trị trong biến đó không thể được đánh hơi:

Không đánh hơi

Lưu ý "Giá trị biên dịch" trống. Trình tối ưu hóa truy vấn ước tính số lượng hàng cao hơn dựa trên phân phối giá trị trung bình trong cột Ngày , (hoặc có thể là dự đoán hoàn chỉnh) dẫn đến kế hoạch song song.

Khi tham số thủ tục được lưu trữ được sử dụng trực tiếp, giá trị của @week được đánh hơi:

Ngửi

Trình tối ưu hóa ước tính số lượng hàng sẽ khớp với các vị từ truy vấn bằng cách sử dụng giá trị '2016 / 02-08', được cắm vào:

and cast(@week as datetime2(3)) <= [Date] 
and [Date] < dateadd(day, 7, cast(@week as datetime2(3)))

Nó đưa ra một ước tính của một hàng, dẫn đến sự lựa chọn của một kế hoạch nối tiếp với tra cứu chính. Các vị từ ở trên không thân thiện lắm cho ước tính cardinality, vì vậy ước tính 1 hàng có thể không chính xác lắm. Bạn có thể thử bật cờ theo dõi 4199 nhưng không có gì đảm bảo ước tính sẽ được cải thiện.

Để biết thêm chi tiết xin vui lòng xem:

Tham số Ngửi, nhúng và các RECOMPILEtùy chọn

Nói chung, cũng có thể việc chạy ban đầu của thủ tục được lưu trữ xảy ra với giá trị rất chọn lọc cho @week, chỉ với một số lượng nhỏ các hàng được mong đợi. Một nguyên nhân có thể khác của sự cố xảy ra khi giá trị rất gần đây của @week được sử dụng cho cuộc gọi ban đầu, trước khi số liệu thống kê được cập nhật để bao trùm phạm vi giá trị này (đây là Vấn đề chính tăng dần ).

Một giá trị đánh hơi rất chọn lọc cho @week có thể khiến trình tối ưu hóa truy vấn chọn một kế hoạch không song song với tìm kiếm chỉ mục và tra cứu khóa. Kế hoạch này sẽ được lưu trữ để sử dụng lại cho các lần thực hiện thủ tục trong tương lai với các giá trị tham số khác nhau. Trong trường hợp thực hiện sau này (với giá trị khác cho @week) chọn nhiều hàng hơn ban đầu, kế hoạch có thể thực hiện kém, vì tìm kiếm + tra cứu khóa không còn là một chiến lược tốt.

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.