Mã tạo kế hoạch khác nhau khi chạy ad-hoc so với trong một thủ tục được lưu trữ


9

Tôi có một câu lệnh xóa đang sử dụng một kế hoạch xấu khi chạy bên trong một thủ tục được lưu trữ, nhưng đang chọn một kế hoạch tốt hơn nhiều khi chạy ad-hoc.

Tôi đã xây dựng lại tất cả các chỉ mục cho các bảng được sử dụng bởi truy vấn và loại bỏ tất cả các bộ đệm. Trình tối ưu hóa vẫn chọn phương án sai cho quy trình được lưu trữ.

Tôi muốn biết lý do tại sao trình tối ưu hóa đang sử dụng một kế hoạch thực hiện khác cho quy trình được lưu trữ so với SQL ad-hoc.

CẬP NHẬT: Tôi đoán chắc chắn đó phải là các tham số - khi tôi chạy mã ad-hoc với biến được mã hóa cứng, tôi có thể nhận được gói "xấu" với giá trị phù hợp (đó là một ngày, các giá trị đã cũ một năm dường như tạo ra kế hoạch "tốt"). Bây giờ hãy cố gắng thực hiện kế hoạch "tốt" trên Proc bằng cách sử dụng một gợi ý truy vấn.

GIẢI PHÁP: Cuối cùng tôi đã nhận được kế hoạch mà tôi muốn bằng cách sử dụng gợi ý TỐI ƯU HÓA CHO UNKNOWN.


Có lẽ đó là thông số đánh hơi . Có truy vấn tham chiếu một biến trong WHEREmệnh đề của nó ?
Nick Chammas

4
Bạn có thể thêm mã xin vui lòng
gbn

Cũng gửi các kế hoạch ở đâu đó xin vui lòng. Như vậy, sẽ rất khó để nói cho bạn biết chính xác lý do tại sao các kế hoạch lại khác nhau.
Aaron Bertrand

OK, thêm thông tin: Tôi không thể đăng các kế hoạch và mã cho đến khi tôi làm xáo trộn chúng một chút. Tôi sẽ cố gắng để có được chúng trong một vài. Kế hoạch cho thủ tục được lưu trữ (xấu) thực hiện quét chỉ mục cụm của một bảng lớn (toàn bộ, tất cả các phân vùng). Sau đó, nó sử dụng một vòng lặp để tìm các hàng từ một bảng nhỏ hơn và sau đó xóa khỏi bảng nhỏ hơn.
Tin nhắn

Kế hoạch cho mã ad-hoc (tốt) thực hiện quét bảng của bảng nhỏ (chỉ có 5-10 hàng) và sử dụng chỉ mục không được nhóm của bảng lớn để tìm hàng nào cần kiểm tra trong PK của cái bàn lớn. Tôi sẽ cố gắng lên kế hoạch thực tế sớm nhất có thể.
thuyết minh

Câu trả lời:


5

Nghi phạm thông thường:

  1. các hằng số trong adhoc, các tham số trong mã
  2. sự không phù hợp của các loại dữ liệu trong mã
  3. thông số đánh hơi

Điểm 1: trình tối ưu hóa có thể chọn kế hoạch tốt nhất cho các hằng số.
Thay đổi hằng số = thay đổi kế hoạch. Một plen tham số là đáng tin cậy

Điểm 2 sẽ giới thiệu các chuyển đổi ngầm định vì ưu tiên kiểu dữ liệu,
ví dụ cột varchar so với tham số nvarchar

Điểm 3: sử dụng mặt nạ tham số hoặc TỐI ƯU HÓA CHO UNKNOWN
Chỉnh sửa: Để kiểm tra: chạy Proc đã lưu, chạy sp_updatestats, chạy lại. Điều này sẽ làm mất hiệu lực các gói được lưu trong bộ nhớ cache tốt hơn sau đó xóa bộ nhớ cache của gói

Chỉnh sửa: sau bình luận của jcolebrand

Bạn có thể vô hiệu hóa việc đánh hơi một số cách. 3 chính là

  • KIẾN NGHỊ. Đây là IMO ngớ ngẩn.
  • TỐI ƯU (sic) CHO UNKNOWN
  • Mặt nạ tham số

Mặt nạ tham số:

DECLARE @MaskedParam varchar(10)
SELECT @MaskedParam = @SignaureParam

SELECT...WHERE column = @MaskedParam

Mặt nạ và gợi ý TỐI ƯU có cùng tác dụng (có thể vì những lý do khác nhau). Nghĩa là, trình tối ưu hóa phải sử dụng số liệu thống kê và phân phối dữ liệu ( Lưu ý: vẫn đang được Mark Storey-Smith kiểm tra ) đánh giá các tham số trên giá trị riêng của chúng ? , hơn là những gì họ đã gọi lần cuối. Trình tối ưu hóa có thể biên dịch lại hay không. SQL Server 2005 đã thêm biên dịch lại mức câu lệnh để có ít tác động hơn

Bây giờ, tại sao một kế hoạch với các tham số "đánh hơi" là "dính" so với các tham số đeo mặt nạ / "không xác định", tôi không chắc chắn.

Tôi đã sử dụng mặt nạ tham số kể từ SQL Server 2000 cho tất cả trừ mã đơn giản nhất. Tôi đã lưu ý rằng nó có thể xảy ra với mã phức tạp hơn. Và tại công việc cũ của tôi, tôi có một số procs báo cáo rằng tôi có thể thay đổi mặc định tham số kế hoạch. Tôi cho rằng phương pháp "sùng bái hàng hóa" dễ dàng hơn một cuộc gọi hỗ trợ.

Chỉnh sửa 2, ngày 12 tháng 10 năm 2011, sau khi trò chuyện

  • Mặt nạ tham số và TỐI ƯU HÓA CHO UNKNOWN có tác dụng tương tự như tôi có thể nói
    Gợi ý sạch hơn mặt nạ nhưng đã được thêm vào với SQL Server 2008.

  • Thông số đánh hơi xảy ra tại thời gian biên dịch.
    VỚI RECOMPILE tạo ra một kế hoạch mới mỗi lần thực hiện. Điều này có nghĩa là sự lựa chọn mặc định kém sẽ ảnh hưởng đến kế hoạch. Ở công việc cuối cùng của tôi, tôi có thể chứng minh điều này một cách dễ dàng với một số mã báo cáo: thay đổi mặc định tham số đã thay đổi kế hoạch bất kể tham số được cung cấp.

  • Bài viết MS Connect này rất thú vị: Sử dụng chỉ mục dưới mức tối ưu trong quy trình được lưu trữ (được đề cập trong một trong các câu trả lời SO bên dưới)

  • Bob Beauchemin cũng đề cập đến nó

Vấn đề nổi bật

  • Liệu đánh hơi vẫn áp dụng với VỚI RECOMPILE? Đó là, nếu trình tối ưu hóa biết loại bỏ kế hoạch, nó có nhằm mục đích tái sử dụng không?

  • Tại sao các kế hoạch đánh hơi "dính"?

Liên kết từ SO:


1. Tham số trong sp là một biến trong mã 2. Một lần nữa, cùng kiểu dữ liệu 3. Tôi đã chạy cả hai với nhiều tham số khác nhau và mỗi lần tôi nhận được cùng một kế hoạch. Tôi xóa bộ nhớ cache sau mỗi lần thử.
thuyết minh

1
Re: điểm 3. Bạn cũng có thể chạy câu lệnh với OPTION (RECOMPILE)hoặc toàn bộ Proc WITH RECOMPILEđể buộc SQL Server bỏ qua các kế hoạch hiện có.
Nick Chammas

3
BTW đó OPTIMIZE, bởi vì Microsoft là một công ty Mỹ. :)
Nick Chammas

1
@Gbn có suy nghĩ gì về việc ngăn chặn / đánh bại thông số đánh hơi không?
jcolebrand

1
@jcolebrand: câu trả lời đơn giản là "không" :-)
gbn

2

Đừng quên rằng các cài đặt ANSI mà bạn đã thiết lập cho kế hoạch kết nối có vai trò trong lựa chọn gói thực hiện. Khi ứng dụng gọi thủ tục được lưu trữ, nó có thể có các cài đặt ANSI khác với kết nối SSMS của bạn.

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.