改进特定的SQL Server查询性能

时间:2013-04-05 16:22:59

标签: sql sql-server performance

我有多个客户端数据库,每天在SQL Server 2008 R2中执行以下几次查询。

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将包含几千条记录,但是数十万条记录是常见的,100,000条或更多条记录是可能的。

两个表中的LookupKey字段是varchar(27)。在大多数情况下,存储在字段中的文本的长度在5到10个字符之间。长度为10-15个字符是常见的,长度超过20个是罕见的。在绝大多数情况下,各个LookUpKeys中的值将是相同的,即将更新少量记录。在极少数情况下,所有记录都将更新。

我遇到的一个问题是:如果我要删除支票Propane.RecordKey.LookupKey&lt;&gt;,我会获得更好的表现吗? System.Param_RecordKey.LookupKey?即如果我要更新所有记录而不仅仅是那些具有不同LookupKeys的记录。我的期望是更新所有记录的时间不仅仅是更新那些已经改变的记录,但我不确定这是真的。

非常感谢有关如何改进此查询的任何建议。


2013年4月9日,新信息。

删除With(TabLock)并在客户端站点测试更改后,结果会混合。在某些情况下,查询执行得更快,在某些情况下要慢得多,并且在许多情况下,处理记录所花费的时间没有显着变化。

由于进行更改并未导致性能显着且可重复的改进,因此我将此问题保持打开并标记为无人接听。我仍然对这个问题的任何帮助感兴趣。

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

答案 2 :(得分: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)