优化sql更新

Posted

技术标签:

【中文标题】优化sql更新【英文标题】:Optimize sql update 【发布时间】:2009-02-06 09:35:59 【问题描述】:

我们有 2 个表格,分别称为 TableToUpdateDates。 我们需要通过查看其他表 Dates 来更新 TableToUpdate 的 EndTimeKey 列。我们在下面运行 sql 来执行此操作,但需要很长时间才能完成。

TableToUpdate 有 6M 条记录。 Dates 表有 5000 条记录。

我们如何优化它?

感谢回复!

update TableToUpdate set
EndTimeKey = DATE_NO
from Dates where EndTime = DATE

【问题讨论】:

请指定您正在使用的 RDBMS。 【参考方案1】:

您可能正在更新 600 万条记录,无论如何这都不会非常快。但是,请查看您的执行计划,看看它是否使用索引。

也可以批量运行,在更新大量记录时通常会更快。在数据库负载很小的下班时间进行更新,这将减少潜在的锁定问题。确保两个表之间的数据类型相同,这样您就不必进行任何隐式转换。

看看你正在更新的表,上面有触发器吗?根据触发器的编写方式,这可能会严重减慢许多记录的更新速度(特别是如果不太聪明的人决定在触发器中放置游标或循环而不是编写基于集合的代码)。

这里还有一些我要添加的东西(我也改变了它显示明确显示加入)

update t
set EndTimeKey = DATE_NO
from TableToUpdate t
Join Dates D on t.EndTime = d.DATE
where EndTimeKey <> DATE_NO

更新已经匹配的记录没有意义。

【讨论】:

【参考方案2】:

有了这么多数据,您最好创建一个 SELECT 查询,该查询会生成一个包含更新值的结果集,因为您希望看到新表。接下来,通过创建表并使用 INSERT INTO 或通过更改 SELECT 添加 INTO 来创建新表,将这些 SELECT 到新表中(可能是 'NewTableToUpdate')。

接下来使用 sp_rename 将“TableToUpdate”重命名为“OLDTableToUpdate”,将“NEWTableToUpdate”重命名为“TableToUpdate”,然后按照您在原始表上的索引创建索引。

根据我的经验,我发现这是实现此类重大变化的最快方法。 HTH。

额外的想法...如果您的表上有一个聚集索引,那么在您的 SELECT 语句中添加一个 ORDER BY 以确保它以与聚集索引相同的顺序插入到您的新表中。这将显着加快索引创建速度。

【讨论】:

【参考方案3】:

您可以在相关字段上设置一些索引(按相关顺序),即:endtimekey 和 endtime。不要期望太多。您可以检查的另一件事是您是否有其他限制来限制查询结果。

您还可以创建一个视图,为每个 tabletoupdate.endtimekey 返回正确的 date_no。

如果您的 dbms 确实支持这些东西,也许您可​​以编写一个存储过程 - 因为这确实会加速更新。

【讨论】:

【参考方案4】:

我在这里注意到几件事,EndTimeKey 真的是一个键吗?如果是这样,它可能有一个索引,如果是这样,速度(或缺乏)将更新索引,同时也进行数据的实际更新,解决方案删除索引,运行更新重新应用索引。

另一个问题可能是 Sql 的事务性质 - 当您执行此更新时,它会记录每个更改,以便在发生故障时回滚。此更新看起来非常简单,因此您可以分批应用它,即

update TableToUpdate setEndTimeKey = DATE_NOfrom Dates where EndTime = DATE
where TableToUpdateId between 1 and 100000

这会将您的更新分成可管理的大小块 - 至少您会知道每个块需要多长时间。

另一种选择是在 EndTime 列上放置一个索引,这可能需要进行全表扫描。

真正的答案是查看正在生成的查询计划。如您所见,查询可能运行缓慢的原因有很多 - 这些只是一些需要快速检查的原因。

【讨论】:

以上是关于优化sql更新的主要内容,如果未能解决你的问题,请参考以下文章

SQL语句效率优化--持续更新

功能更新|DAS推出全局Workload优化功能,实现SQL自动诊断

索引优化驱动SQL优化总结

索引优化驱动SQL优化总结

使用 from 子句优化的 SQL 更新查询

mysql 简单的sql优化示例[不定时更新]