Tôi có một quy trình được lưu trữ thực hiện khủng khiếp. Khi tôi khai báo một biến, đặt giá trị của nó và sau đó sử dụng nó trong mệnh đề where câu lệnh mất hơn một giờ để chạy. Khi tôi mã cứng các biến trong mệnh đề where nó chạy trong chưa đầy một giây.Tham số không hoạt động cũng như mã hóa cứng giá trị
Tôi bắt đầu xem xét những gì đã xảy ra với thông qua kế hoạch thực hiện. Có vẻ như khi tôi thử và chuyển nó một số biến đã khai báo, kế hoạch thực thi sẽ gộp một số Hash Match vì nó chọn giá trị từ một khung nhìn sử dụng một UNION và một biểu thức bảng chung.
/************* Begin of Stored Procedure ***************/ CREATE PROCEDURE GetFruit @ColorId bigint, @SeasionId bigint WITH RECOMPILE AS BEGIN SELECT A.Name FROM [Apple_View] A /* This is the view down below */ INNER JOIN [Fruit] F ON (F.ColorId = @ColorId AND A.FruitId = F.FruitId) WHERE (A.ColorId = @ColorId AND A.SeasonId = @SeasonId) END /************* End of Stored Procedure ***************/ /************* Begin of View ***************/ WITH Fruits (FruitId, ColorId, SeasonId) AS ( -- Anchor member SELECT F.FruitId ,F.ColorId ,F.SeasonId FROM (( SELECT DISTINCT EF.FruitId ,EF.ColorId ,EF.SeasonId ,EF.ParentFruitId FROM ExoticFruit EF INNER JOIN Fruit FR ON FR.FruitId = EF.FruitId UNION SELECT DISTINCT SF.FruitId ,SF.ColorId ,SF.SeasonId ,SF.ParentFruitId FROM StinkyFruit SF INNER JOIN Fruit FR ON FR.FruitId = SF.FruitId UNION SELECT DISTINCT CF.FruitId ,CF.ColorId ,CF.SeasonId ,CF.ParentFruitId FROM CrazyFruit CF INNER JOIN Fruit FR ON FR.FruitId = CF.FruitId )) f UNION ALL -- Recursive Parent Fruit SELECT FS.FruitId ,FS.ColorId ,FS.SeasonId ,FS.ParentFruitId FROM Fruits FS INNER JOIN MasterFruit MF ON MF.[ParentFruitId] = fs.[FruitId] ) SELECT DISTINCT FS.FruitId ,FS.ColorId ,FS.SeasonId FROM Fruits FS /************* End of View ***************/ /* To Execute */ EXEC GetFruit 1,3
Nếu tôi chạy Stored Procedure sử dụng các giá trị thiết lập phải mất hơn một giờ và ở đây là kế hoạch thực hiện.
Nếu tôi chạy Stored Procedure loại bỏ các giá trị DECLARE và SET và chỉ cần thiết lập các khoản đâu tuyên bố sau nó chạy trong vòng chưa đầy một giây và đây là kế hoạch thực hiện:
WHERE(A.ColorId = 1 AND A.SeasonId = 3)
Lưu ý cách biến được mã hóa cứng sử dụng lập chỉ mục trong khi biến đầu tiên sử dụng tập hợp băm. Tại sao vậy? Tại sao các giá trị mã hóa cứng trong mệnh đề where hoạt động khác với các biến được khai báo?
------- đây là những gì cuối cùng thực hiện với sự giúp đỡ của @ user1166147 ------
Tôi đã thay đổi thủ tục lưu trữ để sử dụng sp_executesql.
CREATE PROCEDURE GetFruit @ColorId bigint, @SeasionId bigint WITH RECOMPILE AS BEGIN DECLARE @SelectString nvarchar(max) SET @SelectString = N'SELECT A.Name FROM [Apple_View] A /* This is the view down below */ INNER JOIN [Fruit] F ON (F.ColorId = @ColorId AND A.FruitId = F.FruitId) WHERE (A.ColorId = ' + CONVERT(NVARCHAR(MAX), @ColorId) + ' AND A.SeasonId = ' + CONVERT(NVARCHAR(MAX), @SeasonId) + ')' EXEC sp_executesql @SelectString END
Bạn đã kiểm tra để đảm bảo các loại tham số dữ liệu của bạn phù hợp với kiểu dữ liệu cột? – HackedByChinese
Đây là các biến không phải là tham số. SQL Server không làm thay đổi độ lệch để ước tính chọn lọc sẽ được đoán. Nếu bạn thêm 'OPTION (RECOMPILE)' thì sao? –
sử dụng tùy chọn biên dịch lại. Có cái gì đó gọi là tham số sniffing trong đó máy chủ sql tạo ra kế hoạch truy vấn khác nhau tùy thuộc vào giá trị đầu vào – praveen