2013-04-05 53 views
0

我有多個客戶端數據庫每天在SQL Server 2008 R2中執行以下查詢。提高特定的SQL Server查詢性能

UPDATE Propane.RecordKey 
With (TabLock) 
SET    LookupKey = System.Param_RecordKey.LookupKey 
FROM   Propane.RecordKey INNER JOIN 
        System.Param_RecordKey ON 
        Propane.RecordKey.IndexId = System.Param_RecordKey.IndexId 
        And Propane.RecordKey.RecordNumber = System.Param_RecordKey.RecordNumber      
        AND Propane.RecordKey.LookupKey <> System.Param_RecordKey.LookupKey 
WHERE  (System.Param_RecordKey.ParameterKeyId = @key) 

我在尋找如何使這個查詢儘快運行的任何建議。目前,我的延遲時間可能會持續幾秒到一分鐘或更長時間。

性能不一致,有些情況下許多記錄受到影響的速度相對較快,而其他情況下受影響較少的記錄運行速度較慢。在我的測試機器上,性能一般是可以接受的(即對於超過10,000條記錄,只需幾秒鐘),但是我們的一些客戶出現了明顯的延遲。

這是我無法解釋的極端變化,加上我對如何調整查詢性能的有限知識,使得我不願嘗試可能沒有多大好處並且可能使查詢運行變差的改動。

正在更新的表RecordKey從頻繁(每天幾百到幾千次)讀取,並偶爾更新(每天幾次)。

RecordKey的主索引是IndexId和RecordNumber。 Param_RecordKey具有ParameterKeyId,IndexId和RecordNumber的關鍵字段。即我正在篩選並加入兩個表的主鍵字段。所有這些字段都是整數。

RecordKey將有數十萬到數百萬條記錄。 Param_RecordKey將只有正在更新的記錄。通常Param_RecordKey將包含幾千條記錄,儘管成千上萬條記錄中有10條是常見的,並且100,000條或更多條記錄是可能的。

兩個表中的LookupKey字段都是varchar(27)。在大多數情況下,存儲在該字段中的文本將具有5-10個字符之間的長度。長度爲10-15個字符是常見的,超過20個字符的長度很少。在絕大多數情況下,各個LookUpKeys中的值將是相同的,即很少的記錄將被更新。在極少數情況下,所有記錄都會更新。

我有一個問題是:如果我要刪除檢查Propane.RecordKey.LookupKey <> System.Param_RecordKey.LookupKey嗎?我會得到更好的性能嗎?即如果我要更新所有記錄而不僅僅是那些具有不同LookupKeys的記錄。我的期望是,更新所有記錄的時間會比更新那些已更改的記錄更長,但我不確定這是否屬實。

有關如何改善此查詢的任何建議將不勝感激。


2013年4月9日,新的信息。

刪除With(TabLock)並測試客戶站點的更改後,結果會混合。在某些情況下,查詢的執行速度要快得多,在某些情況下要慢得多,並且在很多情況下,處理記錄花費的時間不會有太大的變化。

由於進行更改並未導致性能顯着且可重複的改進,因此我將此問題留出並標記爲未答覆。我仍然對這個問題的任何幫助感興趣。

+2

是否存在對更新的爭用?這個陳述是否需要是原子的? – Jodrell 2013-04-05 16:31:19

+0

執行計劃在哪裏? – Kermit 2013-04-05 16:38:45

+2

你真的需要WITH(TABLOCK)嗎? – tobias86 2013-04-05 16:50:31

回答

2

表提示TABLOCK可能會對正在更新的表進行獨佔鎖定。這樣的鎖與其他鎖,甚至共享鎖不兼容,並且會影響性​​能。如果一個查詢需要一個獨佔表鎖,它將不得不等待,直到沒有其他的鎖被佔用。刪除提示並讓數據庫引擎決定鎖定策略 - 它很擅長。在你的開發機器上的性能將是可以接受的,因爲你(可能)是唯一訪問該表的人,因此沒有其他鎖被採取

0

在這樣的腳本中看到的一個最好的改進之一是創建一個動態查詢並將該變量轉換爲一個sql,然後執行生成的sql。當然,確保索引重建(或至少統計數據最新)。 DBCC TRACEON 2301和8780也可以提供幫助。

0

我爲你解決了兩個解決方案,第二個解決方案的工作速度應該比現在更快。

UPDATE Propane.RecordKey 
With (TabLock) 
SET    LookupKey = System.Param_RecordKey.LookupKey 
FROM   Propane.RecordKey K , System.Param_RecordKey R 
ON 
       K.IndexId = R.IndexId 
       And K.RecordNumber = R.RecordNumber      
       AND K.LookupKey <> R.LookupKey 
WHERE  (R.ParameterKeyId = @key) 


UPDATE Propane.RecordKey 
With (TabLock) 
SET    LookupKey = System.Param_RecordKey.LookupKey 
FROM   Propane.RecordKey K , System.Param_RecordKey R 
ON 
       K.IndexId = R.IndexId 
       And K.RecordNumber = R.RecordNumber      
       WHERE  (R.ParameterKeyId = @key) and K.LookupKey not in   (Select LookupKey from System.Param_RecordKey)