缓慢更新(主键)

时间:2009-07-14 16:13:50

标签: sql performance primary-key sql-update

update auditdata set TATCallType='12',TATCallUnit='1' from auditdata auditdata 
        inner join Auditdata_sms_12 a_sns
        on auditdata.ID = a_sns.id

当我在上面查询时,执行时间超过10分钟。

这个错误

Auditdata.ID是主键..

如果我运行更新命令是也更新索引??? 这是更新得到的原因很慢

4 个答案:

答案 0 :(得分:2)

这里有几件事情在发挥作用。

首先,SQL语句看起来很糟糕。更新中的“FROM”子句旨在用作JOIN'd更新。由于您正在使用硬编码值更新行,因此无需执行此操作。

其次,更为深奥的是,如果索引完全正如您所说的那样,那么也许您正在处理初始写入或事务日志区域的慢速磁盘I / O(在Oracle中撤消,日志在SQL Server等中。)。

作为一个完整性检查,我会做两件事。一,只更新尚未设置条件的行。许多DBMS产品将很乐意为不变的行执行物理磁盘I / O(尽管许多不这样做)。尝试使用限制。

二,以较小批量应用更新。这对于日志争用和较慢的磁盘确实有帮助。

所以,最初尝试以下内容:

UPDATE auditdata 
   SET TATCallType = '12' 
     , TATCallUnit = '1' 
  FROM auditdata 
 WHERE TATCallType <> '12' 
   AND TATCallUnit <> '1'
   AND EXISTS( SELECT *
                 FROM Auditdata_sms_12 a_sns 
                WHERE a_sns.id = auditdata.ID )

如果你想批量生产,在SQL Server中它很容易:

SET ROWCOUNT 2000

UPDATE ...

(run continually in a loop via T-SQL or by hand until @@ROWCOUNT = 0)

SET ROWCOUNT 0

答案 1 :(得分:1)

查看您的评论,主表包含的行数少于临时表。

尝试使用EXISTS子句(或者在某种意义上,将比较减少到较少的行数(即1500000)

update auditdata set TATCallType='12',TATCallUnit='1' 
from auditdata auditdata 
WHERE EXISTS 
(SELECT id from Auditdata_sms_12 a_sns WHERE a_sns.id = auditdata.ID)

这个想法是限制比较。

编辑:AuditdataSMS12应具有ID索引,以便能够快速获取行。这是您实际查找给定ID的表。

答案 2 :(得分:0)

<强>更新 我在再次阅读初始查询后意识到您没有更新主ID字段,而是更新了其他2个数据字段。请重新阅读我的回复的第一个陈述并作出相应的评论。遗憾。

是否在要更新的任一字段上定义了聚簇索引?集群索引有一些优点,我不知道它们,但它们可能会在更新期间导致大的性能命中。我的理解是对聚簇索引的更新可能导致整个索引必须重新编译。如果表格中有大量数据,这肯定会导致您的问题。

另外,请确保桌面上没有触发器。如果有一个不正常的触发器,它可能会导致相同的性能损失。

答案 3 :(得分:0)

简单选择需要多长时间(例如

 select id from auditdata auditdata 
    inner join Auditdata_sms_12 a_sns
    on auditdata.ID = a_sns.id

)它和它找到了多少条记录?

如果Sql server必须读取所有500万条记录,或者更新一百万条记录并且没有足够的内存或足够快的硬件,那么您的查询可能就不多了。

您可能需要监控Sql server硬件并查看查询计划以查看占用时间的位。