2008-10-17 29 views
60

Một thời gian trước, tôi đã có một truy vấn mà tôi chạy khá nhiều cho một trong những người dùng của tôi. Nó vẫn đang được phát triển và tinh chỉnh nhưng cuối cùng nó được ổn định và chạy khá nhanh, vì vậy chúng tôi đã tạo ra một thủ tục lưu sẵn từ nó.Tham số Sniffing (hoặc Spoofing) trong SQL Server

Cho đến nay, rất bình thường.

Quy trình lưu trữ, mặc dù, là con chó chậm. Không có sự khác biệt về vật chất giữa truy vấn và proc, nhưng thay đổi tốc độ rất lớn.

[Bối cảnh, chúng tôi đang chạy SQL Server 2005.]

Một DBA địa phương thân thiện (người không còn làm việc ở đây) đã xem xét một thủ tục lưu trữ và nói "tham số giả mạo!" (Chỉnh sửa: mặc dù có vẻ như nó có thể còn được gọi là 'tham số sniffing', điều này có thể giải thích tính tương đồng của các lần truy cập Google khi tôi cố gắng tìm kiếm nó.)

Chúng tôi đã tóm tắt một số thủ tục được lưu trữ cho thứ hai, gói các cuộc gọi đến proc bên trong mới này vào bên ngoài có sẵn bên ngoài, được gọi là bên ngoài và, hey mau, nó đã nhanh như truy vấn ban đầu.

Vì vậy, điều gì mang lại? Ai đó có thể giải thích giả mạo tham số?

tín dụng thưởng cho

  • làm nổi bật thế nào để tránh nó
  • cho thấy làm thế nào để nhận ra có thể gây ra
  • thảo luận về các chiến lược thay thế, ví dụ số liệu thống kê, chỉ số, chìa khóa để giảm nhẹ tình hình
+0

Nó không chỉ là một khả năng, đó là một sự chắc chắn - không có những thứ như giả mạo tham số. Đó là tham số đánh hơi. – ErikE

Trả lời

52

FYI - bạn cần phải biết điều gì đó khác khi bạn đang làm việc với SQL 2005 và lưu trữ các tham số có tham số.

Máy chủ SQL sẽ biên dịch kế hoạch thực thi của proc được lưu trữ với thông số đầu tiên được sử dụng. Vì vậy, nếu bạn chạy điều này:

usp_QueryMyDataByState 'Rhode Island' 

Gói thực thi sẽ hoạt động tốt nhất với dữ liệu của tiểu bang nhỏ.Nhưng nếu ai đó quay lại và chạy:

usp_QueryMyDataByState 'Texas' 

Gói thực hiện được thiết kế cho dữ liệu có kích thước Rhode Island có thể không hiệu quả với dữ liệu có kích thước Texas. Điều này có thể tạo ra kết quả đáng ngạc nhiên khi máy chủ được khởi động lại, vì kế hoạch thực hiện mới được tạo ra sẽ được nhắm mục tiêu vào bất kỳ tham số nào được sử dụng đầu tiên - không nhất thiết phải là tham số tốt nhất. Kế hoạch sẽ không được biên dịch lại cho đến khi có một lý do lớn để làm điều đó, như thể số liệu thống kê được xây dựng lại.

Đây là nơi các kế hoạch truy vấn đến, và SQL Server 2008 cung cấp nhiều tính năng mới giúp DBA ghim một kế hoạch truy vấn cụ thể trong thời gian dài bất kể tham số nào được gọi trước.

Quan tâm của tôi là khi bạn xây dựng lại kho lưu trữ đã lưu trữ, bạn đã buộc kế hoạch thực hiện biên dịch lại. Bạn gọi nó với tham số yêu thích của bạn, và sau đó tất nhiên nó đã được nhanh chóng - nhưng vấn đề có thể không có được proc lưu trữ. Nó có thể đã được rằng proc lưu trữ được biên dịch lại tại một số điểm với một tập hợp các thông số bất thường và do đó, một kế hoạch truy vấn không hiệu quả. Bạn có thể không sửa bất cứ điều gì, và bạn có thể phải đối mặt với cùng một vấn đề trong lần khởi động lại máy chủ tiếp theo hoặc kế hoạch truy vấn được biên dịch lại.

+2

vì vậy .... làm thế nào để tránh nó? – thomaspaulb

+3

Nhận cuốn sách tuyệt vời của Grant Fritchey SQL Server 2008 Truy vấn Hiệu suất Chưng cất nơi anh ta đi qua tất cả các tùy chọn của bạn. Mặc dù nó nói năm 2008, nó cũng tuyệt vời cho năm 2005. –

+0

Tôi khuyên bạn nên tìm kiếm hai giải pháp có thể, lần đầu tiên tôi đã thử và thấy công việc, thứ hai tôi nghi ngờ sẽ làm việc nhưng chưa thử trong thực tế. –

26

Có, tôi nghĩ bạn có nghĩa là tham số sniffing, một kỹ thuật mà trình tối ưu hóa SQL Server sử dụng để tìm ra giá trị tham số/dải để có thể chọn thực thi tốt nhất lên kế hoạch cho truy vấn của bạn. Trong một số trường hợp SQL Server làm một công việc nghèo tại tham số sniffing & không chọn kế hoạch thực hiện tốt nhất cho truy vấn.

Tôi tin rằng bài viết blog này http://blogs.msdn.com/queryoptteam/archive/2006/03/31/565991.aspx có giải thích tốt.

Dường như DBA trong ví dụ của bạn đã chọn tùy chọn # 4 để chuyển truy vấn đến một sproc khác đến một ngữ cảnh thủ tục riêng biệt.

Bạn cũng có thể sử dụng với biên dịch lại trên sproc gốc hoặc sử dụng tùy chọn tối ưu hóa cho trên tham số.

+1

+1, nhưng lưu ý rằng "với biên dịch lại" có thể có vấn đề hiệu suất của chính nó. Tôi có xu hướng thử tùy chọn # 4 đầu tiên ... –

+0

Sự hiểu biết của tôi về các phép nối là kiểu tham gia (hợp nhất/băm/vòng lặp) được chọn dựa trên hai yếu tố chính, 1) chỉ mục trên các cột được nối 2) thống kê dự đoán kích thước của việc tham gia. Vì vậy, mỗi lần bạn chạy truy vấn, dựa trên kích thước ước tính của tham gia, nó sẽ chọn tham gia phù hợp. Là lựa chọn tham gia nướng vào một truy vấn được biên dịch? I E. nếu tham số sniffing kém dự đoán kích thước điển hình của tham gia, nó sẽ nướng vào kế hoạch truy vấn các loại kém được lựa chọn tham gia? – AaronLS

24

Cách đơn giản để tăng tốc là gán lại các tham số đầu vào cho các tham số cục bộ trong phần đầu của sproc, ví dụ:

CREATE PROCEDURE uspParameterSniffingAvoidance 
    @SniffedFormalParameter int 
AS 
BEGIN 

    DECLARE @SniffAvoidingLocalParameter int 
    SET @SniffAvoidingLocalParameter = @SniffedFormalParameter 

    --Work w/ @SniffAvoidingLocalParameter in sproc body 
    -- ... 
+1

Giải pháp này giảm thời gian thực hiện truy vấn của tôi là 50%. Không hoàn hảo nhưng tốt hơn! –

+0

Nhưng _why_ điều đó có giúp ích gì không? –

+1

@ TimBüthe: Nó hoạt động bằng cách ngăn chặn SQL Server từ bộ nhớ đệm (hoặc sử dụng một phiên bản được lưu trữ) của một kế hoạch truy vấn cho thủ tục của bạn. Tùy thuộc vào giá trị của tham số của bạn, một kế hoạch thực hiện truy vấn có thể nhanh hơn hoặc chậm hơn giá trị khác. Lần đầu tiên thủ tục của bạn chạy nó sẽ xây dựng một kế hoạch dựa trên giá trị của tham số đầu tiên đó. Chỉ định lại nó cục bộ sẽ làm cho SQL Server sử dụng một kế hoạch mới mỗi lần. –

4

Tham số sniffing là một kỹ thuật SQL Server sử dụng để tối ưu hóa kế hoạch thực hiện truy vấn cho một thủ tục được lưu trữ. Khi bạn lần đầu tiên gọi thủ tục được lưu trữ, SQL Server xem xét các giá trị tham số đã cho của cuộc gọi của bạn và quyết định chỉ mục nào sẽ sử dụng dựa trên các giá trị tham số. Vì vậy, khi cuộc gọi đầu tiên không chứa các thông số rất điển hình, SQL Server có thể chọn và lưu trữ một kế hoạch thực hiện tối ưu phụ liên quan đến các cuộc gọi sau của thủ tục được lưu trữ.

Bạn có thể làm việc này bằng một trong hai

  • sử dụng WITH RECOMPILE
  • sao chép các giá trị tham số cho các biến cục bộ bên trong thủ tục lưu trữ và sử dụng người dân địa phương trong các truy vấn của bạn.

Tôi thậm chí còn nghe nói tốt hơn là không nên sử dụng thủ tục được lưu trữ, nhưng để gửi truy vấn của bạn trực tiếp đến máy chủ. Gần đây tôi đã gặp vấn đề tương tự mà tôi chưa có giải pháp thực sự. Đối với một số truy vấn, bản sao cho các vars cục bộ giúp lấy lại đúng kế hoạch thực hiện, đối với một số truy vấn, hiệu suất sẽ giảm xuống với các vars cục bộ.

Tôi vẫn phải nghiên cứu thêm về cách SQL Server lưu trữ và sử dụng lại các kế hoạch thực thi (tối ưu).

4

Theo kinh nghiệm của tôi, giải pháp tốt nhất để đánh hơi tham số là 'SQL động'. Hai điều quan trọng cần lưu ý là 1. bạn nên sử dụng tham số trong truy vấn sql động 2. bạn nên sử dụng sp_executesql (và không sp_execute), để lưu kế hoạch thực hiện cho mỗi giá trị tham số

+0

Trong một thế giới của SQL Tiêm tấn công, tôi không nghĩ rằng đề xuất SQL động là một ý tưởng tốt. – datagod

+1

Ông cũng khuyến nghị sử dụng các tham số, đó là cách bạn có thể tránh được việc tiêm SQL. –

-2

Thay đổi thủ tục lưu trữ của bạn để thực thi một lô nên tăng tốc độ.

tập tin hàng loạt lựa chọn tức là .:

exec ('select * from order where order id ='''+ @ordersID') 

Thay vì các thủ tục lưu trữ bình thường chọn:

select * from order where order id = @ordersID 

Chỉ cần vượt qua trong các tham số như nvarchar và bạn sẽ nhận được kết quả nhanh hơn.

0

Tôi gặp sự cố tương tự. Kế hoạch thực hiện của thủ tục lưu trữ của tôi mất 30-40 giây. Tôi đã thử bằng cách sử dụng SP báo cáo trong cửa sổ truy vấn và phải mất vài ms để thực hiện như vậy. Sau đó, tôi đã làm việc ra khai báo biến cục bộ trong thủ tục lưu sẵn và chuyển các giá trị của tham số sang biến cục bộ. Điều này làm cho SP thực hiện rất nhanh và bây giờ cùng một SP thực hiện trong vòng vài phần nghìn giây thay vì 30-40 giây.

-1

Rất đơn giản và sắp xếp, Trình tối ưu hóa truy vấn sử dụng kế hoạch truy vấn cũ cho các truy vấn thường xuyên chạy. nhưng trên thực tế, kích thước của dữ liệu cũng tăng lên nên tại thời điểm đó, gói tối ưu hóa mới là yêu cầu và vẫn là trình tối ưu hóa truy vấn bằng cách sử dụng kế hoạch truy vấn cũ. Điều này được gọi là tham số Sniffing. Tôi cũng đã tạo bài đăng chi tiết về điều này. Vui lòng truy cập url này: http://www.dbrnd.com/2015/05/sql-server-parameter-sniffing/

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