微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql – 最快的方式进行大规模更新

假设你有一个约500万条记录的表,一个填充大文本数据的nvarchar(max)列.如果SomeOtherColumn = 1,则以最快的方式将此列设置为NULL.

暴力UPDATE在这里不能很好地工作,因为它将创建大量的隐式事务并且永远占用.

一次进行小批量的50K记录的更新工作,但仍然需要47个小时才能在32个核心/ 64GB服务器上完成.

有什么办法可以更快地做这个更新吗?是否有任何魔术查询提示/表选项牺牲别的东西(如并发)来换取速度?

注意:创建临时表或临时列不是一个选项,因为这个nvarchar(max)列涉及大量数据,因此消耗了大量空间!

PS:是的,SomeOtherColumn已经被编入索引.

解决方法

从一切我可以看到它看起来不像你的问题与索引有关.

关键在于,您的nvarchar(max)字段包含“很多”数据.考虑执行此更新时sql必须执行的操作.

由于您正在更新的列可能超过8000个字符,因此它被非页面存储,这意味着在不为NULL时读取此列的额外工作.

当您运行一批50000次更新时,sql必须将其放置在隐式事务中,以便在出现任何问题时可以回滚.为了回滚它必须将列的原始值存储在事务日志中.

假设(为了简单起见)每列包含平均10,000字节的数据,这意味着50,000行将包含大约500MB的数据,这必须临时存储(简单恢复模式)或永久存储(在完全恢复模式下).

没有办法禁用日志,因为它会危及数据库的完整性.

我对我的狗慢桌面进行了一个快速测试,而运行批次甚至10,000的速度变得非常慢,但是将大小降低到1000行,这意味着大约10MB的临时日志大小正好很好地工作.

我加载了一个350,000行的表,并标记了50,000个更新.大约4分钟后完成,由于它线性缩放,您应该可以在我的1台处理器2GB桌面上大约6小时内更新我的狗慢桌面上的整个5百万行,所以我希望在您的强大的服务器支持下更好的由SAN或某事.

您可能希望作为选择运行更新语句,仅选择主键和大型nvarchar列,并确保运行速度与预期的一样快.

当然,瓶颈可能是其他用户锁定服务器上的存储或内存的争议,但是由于您没有提及其他用户,我将假设您以单用户模式为该数据库.

作为优化,您应确保事务日志位于与数据不同的物理磁盘/磁盘组上,以最小化查找时间.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐