0
Posted on Monday, January 04, 2016 by 醉·醉·鱼 and labeled under
引用: http://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/
http://www.brentozar.com/archive/2013/12/recompile-hints-and-execution-plan-caching/
http://www.sqlpass.org/summit/2014/PASStv.aspx?watch=p-6ii2NiUI0


  1. SP_RECOMPILE 在不知道怎么改的时候,一般的临时方案就是sp_recompile. 
    EXEC sys.sp_recompile 'Get_OrderID_OrderQty' 
    GO
  2. WITH RECOMPILE 能够工作,但是这样做会没有cached query plan,也没有DMV data。
    ALTER PROCEDURE Get_OrderID_OrderQty
     @ProductID INT
     WITH RECOMPILE
    AS 
    
    SELECT SalesOrderDetailID, OrderQty
    FROM Sales.SalesOrderDetail
    WHERE ProductID = @ProductID;
  3. OPTION RECOMPILE 比上面稍微好点,能够cached 最后一次执行的query plan,DMV里面也能够看到数据了。
    ALTER PROCEDURE Get_OrderID_OrderQty
     @ProductID INT
    AS 
    
    SELECT SalesOrderDetailID, OrderQty
    FROM Sales.SalesOrderDetail
    WHERE ProductID = @ProductID OPTION(RECOMPILE);
  4. 核武器 - DBCC FREEPROCCACHE 世界一下清净了,所有的都需要重新compile和cache。但这只是短暂的,等下一次糟糕的query plan被cache起来以后,问题还是会出现。
  5. Dynamic query?这个看上去是个不错的选择。但实际上我还是发现,我需要加上OPTION(RECOMPILE),否则,第一次执行的query plan会被cache起来被第二次执行用掉,问题依旧。而加上以后,其实就是第三个方案一样了。
    ALTER PROCEDURE Get_OrderID_OrderQty
     @ProductID INT
    AS 
    
    DECLARE @sql NVARCHAR(MAX) = N''
    
    SET @sql = 'SELECT SalesOrderDetailID, OrderQty
    FROM Sales.SalesOrderDetail
    WHERE ProductID = @ProductID OPTION(RECOMPILE)'
    
    EXEC sys.sp_executesql @sql, N'@ProductId INT', @ProductID
    
    GO
附上方案5的IO和执行计划
SET STATISTICS IO  ON

EXEC Get_OrderID_OrderQty @ProductID=870

EXEC Get_OrderID_OrderQty @ProductID=897

SET STATISTICS IO OFF



事实上,这里涉及到SQL SERVER的tipping point了。所以,在这个例子里面,我们只能够加上OPTION(RECOMPILE)了。至少我现在还没有想出什么好方法。
0
Responses to ... 关于Parameter sniffing的那些事儿 - 怎么解决Parameter sniffing

Post a Comment