我有一个非常大的表:超过20万行,我需要更新大约5% - 或100万行。
不幸的是,我正在更新用作聚簇索引的(int)列。
我的问题是: 更新这些行的最快方法是什么?
我尝试过直接更新行:
update t1
set t1.groupId = t2.groupId
from
table t1
join newtable t2 on t1.email = t2.email
但这需要太长时间(我在3小时后停止了)
我认为这是因为整个行(有2个日期时间,2个varchars和2个int)正在为每次更新移动。
如果我首先删除聚簇索引,然后执行更新,然后重新创建聚簇索引,该怎么办?会更快吗?
注意:我在电子邮件上有非聚集索引,以防有人认为它是查询的选择部分很慢。不是。
答案 0 :(得分:8)
这就是我所做的(而且速度要快得多):
这使整个过程缩短到几秒钟。 是的,约15秒内约有100万行。
第二步是至关重要的,因为外键强制更新在相关表上执行某种线程,每个表都有大量行。
由于这些外键查找,物理读取次数增加了两倍。
我不确定为什么SQL Server需要这样做,但我的猜测是它仍然执行完整性检查,即使我没有更新该列但是我正在移动整行(群集列更新)。 / p>
作为旁注,我还尝试分批运行更新:
update top(1000) t1
set t1.groupId = t2.groupId
from
table t1
join newtable t2 on t1.email = t2.email
这很好(似乎每批可扩展到大约10K),但每批次仍然是1-2分钟。
总之,我已经了解到,对于批量更新,暂时删除索引可能非常有用。
答案 1 :(得分:2)
我认为之前的评论是正确的。你有点回答了自己的问题。
因为
聚簇索引排序和存储 表中的数据行基于它们 键值(source msdn),
您可能最好只删除聚集索引(将索引保留在电子邮件中)。完成操作后,重新创建聚簇索引。 只要groupid没有涉及任何其他索引,我就不会触及它们。如果组ID包含在其他索引中,则删除它们。我会留下至少一个电子邮件索引,只是为了加快加入。
答案 2 :(得分:-2)
为什么不执行以下操作:
这应该更快。