2013-04-05 36 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)