【问题标题】:Updating a large (280M rows) table with anonymised data使用匿名数据更新大型(2.8 亿行)表
【发布时间】:2016-12-11 15:00:48
【问题描述】:

我们有一个正在迁移到新环境的生产数据库,在项目处于开发阶段时,客户要求对某些列和某些表中的数据进行匿名处理。

供应商提供了替换数据的脚本 - 例如:

UPDATE ThisTable SET Description = 'Anonymised ' + TableKey

现在的问题是有几个表有数百万行。最大的是 284,000,000 行。

当然,由于锁、TempDb 和行版本、日志文件等原因,上述语句永远不会适用于这样的表。

我有一个之前使用过的脚本,它本质上执行以下操作:

我目前的做法:
1.创建源表PK的临时表(并在PK上创建索引)。
2. 从临时表中选择前 n 个 PK 并处理源表中的相应行。
3. 从临时表中删除前 n 个 PK
4. 从第 2 步开始重复

这很好用——它提供了合理的性能(并且做了一些能够预测结束时间的指标)。但是,在大表上运行它会得到 4 天的预测运行时间!

我采取的其他措施是将数据库置于简单恢复模式。

我们拥有对服务器的独占访问权限,并且可以用它“做我们想做的事”。

核心问题是我们正在讨论大量行。一种想法是 BCP OUT 到文本文件,脱机处理,然后 BCP 输入。但是,我们仍在处理具有 284,000,000 行的文本文件!

问:
那么 - 关于如何实现上述目标的任何其他想法?我错过了一种“简单”的方法吗?

【问题讨论】:

  • 您能否提供一些示例来说明您将如何匿名数据?
  • 分批运行.....
  • 如果您尝试一次全部更新,实际会发生什么?我不明白为什么拆分它会使其更快。我曾经使用基于主键的row_number,然后写出每万条记录的键,使用row_number % 10000 = 0找到,然后我可以一次删除10,000个键。
  • 使用上面的简单 sql 一次全部更新会导致 TempDb 在尝试保存所有 RowVersions 时占用磁盘空间。也许增加 TempDb 大小和相关的磁盘空间会起作用。请记住,在查询运行大约 4.5 小时后更新失败。
  • 所有我能想到的尝试是在进程之间拆分批次,例如将临时表中的范围标记为 a、b、c、d 等 - 然后进行一些并发处理 - 说,您可能已经认为它会遇到瓶颈,并且乐观地认为拥有 10 个进程会快 ​​10 倍 - 在您编写和研究优化时 - 它可能已经完成

标签: sql-server tsql sql-server-2008-r2


【解决方案1】:

第 1 步用名称创建相同的表结构,即 tablename+temp

第 2 步现在从 tablename 中选择插入到 tablename+temp 中。

ie 插入到 tablenametemp 从表名中选择列“匿名”+ TableKey 作为描述。

步骤 3 重命名 tablename 为 tablename1 和 tablename+temp 为 tablename

第4步删除tablename1(验证后)

请注意,如果您有约束创建也请重命名它们。

【讨论】:

  • 肯定会完成所有的工作,而且还有更多工作要做,而更新将单独完成。它可能会避免记录锁定,但我认为数据库是让他做他想做的事 - 所以我不明白他的记录锁定问题
  • 我同意@AndrewDeighton - 这是我们已经在源表上可以做的事情。我为其他用户锁定表没有问题 - 我们拥有对数据库的独占访问权限。关于“锁定问题” - 我可能不正确(回想过去)。但是,我们在 TempDb 填满 RowVersions 的简单更新时遇到问题。
猜你喜欢
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多