在100mm记录上使用JOIN进行更新,如何做得更好?(在T-SQL中)


11

实际上,我需要更新单个表中的1亿条记录,通过用一个ID替换列的varchar值来规范化该表。(我说“替换”,但实际上我正在将ID写入另一列。)

我想要实现的是对数据集进行规范化。尚未规范化的数据没有索引。我的想法是,我不会在等待时在原始值上建立索引,而是在更新完成后索引将要用tinyint值替换varchar值的外键。

UPDATE A
SET A.AutoClassID = B.AutoClassID
FROM AutoDataImportStaging.dbo.Automobile as A
JOIN AutoData.dbo.AutoClass as B on (A.AutoClassName = B.AutoClassName)

背景

  • 在Server 2008 R2上使用MSSQL 2008 R2
  • 服务器有8 GB RAM
  • 服务器具有一个RAID10和7200 RPM SATA(我知道这不是很好,在生产中,它只能读取数据,而不能写入数据;加上最近的HD短缺使得这成为必需的成本)
  • 服务器具有双四核Xeon CPU
  • 机器没有做任何其他事情(当前专用于开发人员,仅此过程)
  • 打开了简单的日志记录(?-但是它仍会记录下来以便可以回滚吗?)
  • 请注意,该查询引用了两个不同的数据库,因此值得
  • 表中要更新的记录的“宽度”为455字节

执行期间的资源

  • 物理RAM已用完
  • 磁盘I / O已用尽
  • CPU几乎什么也没做(扼要点是I / O)
  • 运行时间已经有14个小时了!

我怀疑有些事情,例如我需要在原始数据上建立索引,即使在规范化更新后将删除列(AutoClassName)时也是如此。我还想知道是否应该一次循环遍历一个表而不是JOIN,这在我开始时似乎很荒谬,但现在看来它会更快。

如何为剩余的规范化更新(类似于此方法)更快地更改方法?

Answers:


7

您正在尝试将其作为单个(非常大的)交易进行。而是以较小的批次进行更新。

您还将受益于:

  • AutoData.dbo.AutoClass.AutoClassName上的临时索引
  • 更多RAM。还有更多的RAM。

1
+1我同意使用该TOP子句进行批量更新。那就是我的方法。
汤玛斯·斯金格

如果我执行UPDATE TOP,那么我需要WHERE子句(WHERE AutoClassID为NULL)吗?WHERE子句不会带来新的性能影响(我现在不做的表扫描)。毫无疑问,这将减少我在JOIN中遇到的RAM问题。
克里斯·阿德拉尼亚

我的回应早就该了,但就我而言,SET ROWCOUNT被证明是最有效的。
克里斯·阿德拉尼亚

10

我会采取另一种方法。

无需更新现有表,只需构建一个包含所需内容的新表即可。

这几乎肯定会更快:

SELECT DISTINCT
    AutoClassID,
    <Other fields>
INTO
    AutoDataImportStaging.dbo.Automobile
FROM
    AutoData.dbo.AutoClass

如当前所写,发生了许多逻辑运算:

  • 读取A.AutoClassName的所有值
  • 读取B.AutoClassName的所有值
  • 比较A和B值
  • 在匹配集中,读取B.AutoClassID的所有值
  • 通过存在的任何索引将A.AutoClassId的现有值更新为B.AutoClassId值

这听起来像是一种不错的简单方法,尤其是考虑到我遇到的磁盘I / O问题。感谢您如此迅速的回答。
克里斯·阿德拉尼亚

1
我建议您再次检查日志和数据文件中是否有足够的可用空间。如果文件是自动增长的,性能将大打折扣。我经常看到人们运行一些大型的一次性更新并自动增长他们的日志文件而没有意识到。
达林海峡

5

一次将表循环一行,这不会更快!

如您所怀疑并得到您的确认,这将是I / O绑定-拥有一个磁盘,读取,写入,事务日志和(任何)临时工作空间都将争夺同一I / O。

简单恢复仍将记录事务,但是该日志将由检查点清除。初始日志大小和自动增长设置可能会导致某些I / O速度变慢-事务日志将需要增长以适应更改。

您是否尝试过索引AutoClassName字段?有多少个不同的AutoClass值?

您可能需要根据I / O的限制来批处理更新。所以更新一百万,检查点,重复...。


只有15个不同的AutoClass值。您的评论证实了我的许多怀疑(和痛苦!)。感谢您的回答。
克里斯·阿德拉尼亚

3

为连接字段创建索引。

完成后,您始终可以删除索引。

如果索引没有显着提高更新性能,我将感到非常惊讶。


我相信索引会改善。我想问题是,它们是否比创建索引所需的时间有所改善(仅用于一种用途)。大概是。:)
克里斯·阿德拉尼亚

3

导出所需的方式,创建新表并重新导入。作为奖励,万一发生奇迹,您将获得数据副本作为备份。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.