将7亿行更新为相同的值


12

我有一个数据仓库(oracle),在这里我需要为所有7亿行的列设置相同的值。

我没有管理员权限,也没有管理员权限,因此需要使用基本sql来完成,并且不会创建临时表。

更复杂的问题是,如果我尝试仅执行一个简单的更新(其中1 = 1),则它会耗尽重做空间。

我现在运行它的方式是这样的循环:

loop
  update mytable set mycolumn = '1' where mycolumn is null and rownum < 50000;
  commit;
end loop

但是我知道这可能很幼稚,必须有一个更快,更优雅的解决方案。


该表是否已分区?
杰克说,请尝试topanswers.xyz 2011年

我不相信 有几个索引,但是没有一个索引涉及我要更新的列。
owook

Answers:


4

如果有足够的空间,则可以使用最少的撤消/重做来进行CTAS。如果您有任何索引,那么以其他方式进行操作将非常缓慢,并且会疯狂生成日志记录。

如果您有一个没有任何二级索引的IOT,或者只有一个表集群,则可以逐步执行块中的主键/集群键更新,而不必重新扫描整个表以查找尚未更新的字段。

- 编辑

我无法创建辅助表...有几个索引,但是它们都不涉及我要更新的列。

然后,我建议将表拆分为多个块,以便使用要索引的内容进行处理(即使它是单列,也可以将其拆分为值的范围)。这将执行一次FTS,而不是像在您的表中那样对每个块执行一次码。您将不得不进行大量的重做,并且也将消灭您的撤消空间(因此,以后不会出现闪回)

--edit2

如果您可以添加/重命名/删除列,则可以非常高效地完成此操作,但仅限于11g


1
如果您的DBA允许您这样做NOLOGGING,这将使备用状态失效。
Gaius

的确,事后备份也是个好主意-但这是仓库,nologging也是仓库的工具
杰克说,请尝试topanswers.xyz 2011年

我无法创建辅助表,即使只有临时表,肯定也没有第二个表大。
owook

您的11g链接看起来很有希望,但是我看到那里的评论说,对于60m的表,由于必须为每一行设置值,它仍然非常慢。由于我的桌子大小是该桌子的10倍,因此该方法可能不会有所改进。
owook

@owook否,在11g上,此操作非常快捷,并且不会为“某些类型的表(例如,没有LOB列的表)”的每一行设置值。在您的部分表格上尝试(create table foo as select * from bar where rownum<100000
杰克说,请尝试topanswers.xyz 2011年

1

如果您使用的是11g,请删除该列,然后将其添加为具有默认值的NOT NULL列。这是违反直觉的,但是Oracle会将默认值存储在表的定义中,并在运行时替换默认值。

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.