2015-10-21 45 views
0

我是一家醫療自動化公司的DBA。我們有1個客戶正在使用我們的應用程序,這位客戶是1400名客戶中唯一受到影響的客戶。在隨機時間,有一個需要HOURS運行的存儲過程。我自己和另一位數據庫管理員在他們提出問題時一直在進行故障排除和診斷,但它又一次發生,我們感到有些不知所措。長時間運行程序

我相信當它進入這個「車轍」時,這是因爲緩存的執行計劃不好。我接下來要做的是爲該存儲過程運行一個SP_Recompile,並讓它每次重新編譯,但是誰又說是不是再次緩存壞計劃。我添加了MAXDOPS,因爲我們認爲這可能是一個並行的問題,但這些都沒有幫助。

我們將其縮小到一個「步驟」,我們創建了一個調試數據庫來捕獲數據。通常這一步不到5分鐘即可完成。它現在需要大約4-5個小時。我在代碼的下面包含了TSQL片段。任何建議,批評,或平坦的幫助非常感謝!謝謝!

insert into DBAdiag.dbo.dumbcodedebug (note, createddate) 
values ('PatientAuditLog Insert Start',getdate()) 

SET @StartTime = GETUTCDATE(); 
SET IDENTITY_INSERT [XTArchive].dbo.PatientAuditLog ON; 
INSERT INTO [XTArchive].dbo.PatientAuditLog (a.[PatientAuditLogID],a.[PatientHistoryCrossRefID],a.[PatientFieldNameTypeID],a.[OldValue],a.[NewValue],a.[CreatedDate]) 
SELECT a.[PatientAuditLogID],a.[PatientHistoryCrossRefID],a.[PatientFieldNameTypeID],a.[OldValue],a.[NewValue],a.[CreatedDate] FROM dbo.PatientAuditLog a WITH (NOLOCK) 
LEFT JOIN [XTArchive].dbo.PatientAuditLog b on b.PatientAuditLogID = a.PatientAuditLogID 
WHERE a.CreatedDate <= @ArchiveProcessStartTime AND b.PatientAuditLogID IS NULL 
AND EXISTS(SELECT 1 FROM [XTArchive].dbo.PatientHistoryCrossRef e1 where e1.PatientHistoryCrossRefID = a.PatientHistoryCrossRefID) 
option (maxdop 6) 


SELECT @RowCount = @@ROWCOUNT; 
SET IDENTITY_INSERT [XTArchive].dbo.PatientAuditLog OFF; 
PRINT N'Insert into PatientAuditLog;' + convert(varchar(11), @StartTime, 101) + ' ' + convert(varchar(13),@StartTime,114) + ';' + convert(varchar(11), getutcdate(), 101) + ' ' + convert(varchar(13),getutcdate(),114) + ';' + CAST(@RowCount AS VARCHAR(10)) + ';' + 'PatientAuditLog' + ';' + '530' 

insert into DBAdiag.dbo.dumbcodedebug (note, createddate) 
values ('PatientAuditLog Insert end',getdate()) 
+0

您可以完全停用計劃緩存。最簡單的方法是在映射到參數的proc中定義虛擬變量。 https://www.mssqltips.com/sqlservertip/3257/different-approaches-to-correct-sql-server-parameter-sniffing/ – bic

+0

既然你說你爲一家醫療保健公司工作,你可能想要檢查你是否應該全部使用NOLOCK。你確定丟失和/或重複的行嗎? http://blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere/ –

回答

0

我遇到了運行個別查詢類似的問題。在這些情況下,這個問題在查詢計劃中似乎始終是低效的,在這種情況下使用了嵌套循環連接而不是其他算法。

我通過在有問題的查詢上使用查詢提示來解決此問題:option (merge join, hash join)。除非有索引,否則其中一個表真的非常小,我發現嵌套循環連接是最糟糕的算法。

我不確定這是否是您的問題。您可以隱藏查詢的執行計劃並檢查它們是否正在爲此特定客戶端進行更改。

+0

這是平均每晚插入約25萬條記錄。但是,此步驟以前只需要大約2分鐘即可運行。最近,這是2小時左右,一些奇數分鐘的環島。未對應用程序進行任何更改,並且客戶端不報告對SQL環境所做的更改。違揹我們的意願,客戶端DBA運行freeproccache(OMG I KNOW)。仍在花時間運行。感謝所有的評論。我正在查看每條評論和評估! – JDonahoe

0

這是一個難以回答的問題 - 我要寫的是比「回答」更多的意見。

但是......

如果你有上百個客戶端的所有執行相同的查詢(大概在相同的架構,使用相同的DDL等),「錯誤的查詢計劃」的假設將需要進一步的解釋。

我想說,你的客戶之間存在一些其他差異,這就解釋了這一點。這個客戶有更多的數據嗎?他們運行這個查詢的頻率有什麼不同(它似乎是一個歸檔過程;據推測,每天運行一次意味着每次運行的行數都要考慮)。

如果您可以顯示查詢的查詢計劃,我們可能會提供幫助。

最後 - 我累了,所以可能會丟失一些明顯的東西 - 我認爲左連接意味着你總是插入一個NULL的PatientAuditLogID記錄;這是真的嗎?看起來它想成爲主鍵。