Sql-Server

如何只清除目前會話中的查詢計劃?

  • April 18, 2016

我正在一個非常繁忙的伺服器上調整查詢,我不想清除記憶體,使用DBCC FREEPROCCACHE;

我知道它至少會導致 CPU 峰值,在這種情況下我不想要它。

在本文中,它展示瞭如何僅為特定數據庫清除記憶體。

-- Example 2 (Ballpeen hammer)
-- Remove all elements from the plan cache for one database  
-- Get DBID from one database name first
DECLARE @intDBID INT;
SET @intDBID = (SELECT [dbid] 
               FROM master.dbo.sysdatabases 
               WHERE name = 'AdventureWorks');

-- Flush the procedure cache for one database only
DBCC FLUSHPROCINDB (@intDBID);

我想做這樣的事情:

-- Example 3 (Scalpel)
-- Remove one plan from the cache
-- Get the plan handle for a cached plan
SELECT cp.plan_handle, st.[text]
FROM sys.dm_exec_cached_plans AS cp 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
WHERE [text] LIKE N'%/* GetOnlineSearchResultsMonday %';

-- Remove the specific plan from the cache using the plan handle
DBCC FREEPROCCACHE (0x05000800F7BA926C40C15055070000000000000000000000);

有什麼方法可以找到我正在處理的查詢,或者至少在記憶體中找到我自己的會話?

我正在調整以下查詢:

checkpoint

set statistics io on 
set statistics time on


   SET NOCOUNT ON;

   DECLARE @OrderStartDate DATETIME 
   DECLARE @OrderEndDate DATETIME 

   SELECT @OrderStartDate = '27-FEB-2016'
   SELECT @OrderEndDate = '28-FEB-2016'

   SELECT 
          op.lngPaymentID
         ,op.strBxOrderNo
         ,op.sintPaymentTypeID
         ,op.strCurrencyCode
         ,op.strBCCurrencyCode
         ,op.decPaymentAmount
         ,op.decBCPaymentAmount
         ,ap.strAccountCode
         ,o.sintMarketID
         ,o.sintOrderChannelID
         ,o.sintOrderTypeID
         ,CASE WHEN opgv.lngpaymentID IS NULL THEN NULL 
                    -- Not a Voucher = Null
               WHEN gvp.strIssuedBxOrderNo IS NULL THEN 0 
               ELSE 1 END AS [IsPromoVoucher] 
                    -- Is a Voucher - check type
         ,o.sdtmOrdCreated

   FROM    tablebackups.dbo.tblBOrderItemOrderComplete com

           INNER JOIN tablebackups.dbo.tblBOrderPayment op 
                   on op.strBxOrderNo = com.strBxOrderNo

           INNER JOIN tablebackups.dbo.tblBOrder o 
                   ON op.strBxOrderNo = o.strBxOrderNo

           INNER JOIN tablebackups.dbo.tblBOrderItem as oi 
                   on com.strBxOrderNo = oi.strBxOrderNo 
                  AND com.sintOrderSeqNo = oi.sintOrderSeqNo

           INNER JOIN tablebackups.dbo.tblBAccountParticipant ap 
                   ON o.lngAccountParticipantID = ap.lngParticipantID

           LEFT OUTER JOIN tablebackups.dbo.tblBOrderPaymentGiftVoucher opgv 
                        ON op.lngPaymentID = opgv.lngPaymentID

           LEFT OUTER JOIN tablebackups.dbo.tblBGiftVoucher gv 
                        ON opgv.strVoucherNumber = gv.strVoucherNumber

           LEFT OUTER JOIN tablebackups.dbo.tblBGiftVoucherPromotion gvp 
                        ON gvp.strIssuedBxOrderNo = gv.strIssuedBxOrderNo

   WHERE   com.LoadDate >= @OrderStartDate
   AND     com.LoadDate < @OrderEndDate
   AND     o.sdtmOrdCreated >= @OrderStartDate
   AND     oi.decCatItemPrice > 0



set statistics io off
set statistics time off

Marcello,您的問題似乎已經有了答案,儘管稍作修改。

查詢:

SELECT cp.plan_handle, st.[text]
FROM sys.dm_exec_cached_plans AS cp 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
WHERE [text] LIKE N'%/* GetOnlineSearchResultsMonday %';

包含術語'%/* GetOnlineSearchResultsMondy %',這是一個萬用字元搜尋,用於定位要從記憶體中刪除的特定計劃。如果您使用包含在您嘗試調整的查詢中的搜尋詞執行它,它應該返回一個計劃句柄,然後可以使用DBCC FREEPROCCACHE

-- Remove the specific plan from the cache using the plan handle
DBCC FREEPROCCACHE (0x05000800F7BA926C40C15055070000000000000000000000);

我建議也許使用以下方法來辨識查詢:

SELECT cp.plan_handle, st.[text]
FROM sys.dm_exec_cached_plans AS cp 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
WHERE [text] LIKE N'%CASE WHEN opgv.lngpaymentID IS NULL THEN NULL%';

假設該字元串未在其他查詢中使用,結果應該只返回幾行。然後,您將查看該st.[text]列以確保您擁有正確的 plan_handle,然後使用該 plan_handleDBCC FREEPROCCACHE將其從計劃記憶體中刪除。

作為旁注,我會非常小心地針對實時生產系統執行 SSMS 會話 - 這可能是災難的根源,因為很容易忘記您正在生產伺服器上工作。

引用自:https://dba.stackexchange.com/questions/135624