0

I have the following query which is being executed in SQL Server 2008 R2 several times a day on multiple client databases.

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)

I am looking for any suggestion on how to make this query run as quickly as possible. Currently I am having delays which can last from a few seconds to a minute or more.

The performance is not consistent, with some cases where many records are affected are running relatively quickly and other cases with many fewer affected records running quite slowly. On my test machine the performance is generally acceptable (i.e a few seconds for 10,000+ records), but there is significant delays occurring on some of our clients.

This extreme variation which I am unable to account for, combined with my admittedly limited knowledge of how to tweak query performance, makes me reluctant to experiment with alterations which may not show much benefit and might make the query run worse.

The table being updated, RecordKey, is read from frequently (hundreds to thousands of times a day) and updated occasionally (a few times per day).

RecordKey's primary index is IndexId and RecordNumber. Param_RecordKey has key fields of ParameterKeyId, IndexId, and RecordNumber. I.e. I am filtering and joining on the primary key fields of both tables. All these fields are ints.

RecordKey will have hundreds of thousands to a few million records in it. Param_RecordKey will have just the records being updated. Typically Param_RecordKey will contain a few thousand records, though 10's of thousands of records are common and 100,000 or more is possible.

The LookupKey field in both tables is varchar(27). In most cases the text stored in the field will have a length between 5-10 characters. Lengths of 10-15 characters are common and lengths over 20 are rare. In the vast majority of cases the values in the respective LookUpKeys will be the same, i.e. few records will be updated. In rare cases ALL of the records will be updated.

One question I have is: Would I get better performance if I were to remove the check Propane.RecordKey.LookupKey <> System.Param_RecordKey.LookupKey? i.e. if I were to update all records and not just those with different LookupKeys. My expectation is that the time to update all the records would be greater than just updating those that have changed, but I'm uncertain this is true.

Any advice on how to improve this query would be greatly appreciated.


April 9th 2013, New info.

After removing the With (TabLock) and testing the changes at the client's site, the results are mixed. In some cases the query executed much faster, in some cases much slower, and in many cases there was no significant change in how long it took to process the records.

Since making the change did not result a significant and repeatable improvement in performance, I'm leaving this question open and marked as unanswered. I am still interested in any assistance with this problem.

4

3 回答 3

2

表提示 TABLOCK 可能会在正在更新的表上获取排他锁。这样的锁不兼容其他锁,甚至是共享锁,会影响性能。如果查询需要独占表锁,则必须等到没有其他锁被占用。删除提示,让数据库引擎决定锁定策略——它非常擅长。您的开发机器上的性能是可以接受的,因为您(可能)是唯一访问该表的人,因此没有其他锁被占用

于 2013-04-05T17:06:28.377 回答
0

我在带有变量的此类脚本中看到的最佳改进之一是创建动态查询并将变量转换为 sql,然后执行生成的 sql。当然,在执行此操作时,请确保重建索引(或至少更新统计信息)。DBCC TRACEON 2301 和 8780 也可以提供帮助。

于 2015-05-20T18:11:27.190 回答
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)
于 2016-01-19T21:53:00.877 回答