在大量更新期间处理 Oracle ARCHIVELOG
Dealing with Oracle ARCHIVELOG during huge updates
需要在数据库中所有 table 的所有行中全局更新具有元数据的列。假设每个 table 都有一列 MY_META
并且目标大致是
update ANOTHER_TABLE set MY_META = 'HELLO'
每个 table.
估计总行数为 2e9
。
假设 ARCHIVELOG 模式打开,那么在这些更新期间,将消耗大量额外的 space。
更新过程计划在生产数据库中与业务交易同时进行运行,不应丢失。
最简单的开始是为 ARCHIVELOG 文件临时安装大量硬件。
有没有一种优雅的方法可以通过编程或调整来实现相同的目标"secret options"?
经过您的说明,我了解到:
- 对于每个 table,您有一个值
MY_META
,您希望将其作为 初始 值分配给每一行。
- 您不介意删除
MY_META
并重新创建它。
在这种情况下,我建议您删除 MY_META
并使用默认值重新创建它。如果您这样做,Oracle 将不会用您的初始值更新每条记录,并且生成的重做量将是最小的。
缺点是 ALTER TABLE
命令虽然非常快,但会在您处理每个 table 时短暂锁定它。它还将使依赖于 MY_META
列的包无效。
这是该方法的演练,附有评论:
-- Set up your current state
DROP TABLE my_big_table;
CREATE TABLE my_big_table (a number, my_meta varchar2(30) not null);
INSERT INTO my_big_table (a, my_meta) SELECT rownum, 'GARBAGE' FROM dual CONNECT BY rownum <= 100000;
-- Drop the my_meta column and replace it with one having a default value
ALTER TABLE my_big_table DROP COLUMN my_meta;
ALTER TABLE my_big_table ADD my_meta varchar2(30) default 'INITIAL_VAL_FOR_TABLE' not null;
-- Look at my table -- you will see every row has your initial value
SELECT * FROM my_big_table;
-- Update some data
update my_big_table set my_meta = 'UPDATED_VALUE' WHERE a <= 15;
-- Look at my table -- you will see every row has your initial value except the first 15.
SELECT * FROM my_big_table order by a;
需要在数据库中所有 table 的所有行中全局更新具有元数据的列。假设每个 table 都有一列 MY_META
并且目标大致是
update ANOTHER_TABLE set MY_META = 'HELLO'
每个 table.
估计总行数为 2e9
。
假设 ARCHIVELOG 模式打开,那么在这些更新期间,将消耗大量额外的 space。
更新过程计划在生产数据库中与业务交易同时进行运行,不应丢失。
最简单的开始是为 ARCHIVELOG 文件临时安装大量硬件。
有没有一种优雅的方法可以通过编程或调整来实现相同的目标"secret options"?
经过您的说明,我了解到:
- 对于每个 table,您有一个值
MY_META
,您希望将其作为 初始 值分配给每一行。 - 您不介意删除
MY_META
并重新创建它。
在这种情况下,我建议您删除 MY_META
并使用默认值重新创建它。如果您这样做,Oracle 将不会用您的初始值更新每条记录,并且生成的重做量将是最小的。
缺点是 ALTER TABLE
命令虽然非常快,但会在您处理每个 table 时短暂锁定它。它还将使依赖于 MY_META
列的包无效。
这是该方法的演练,附有评论:
-- Set up your current state
DROP TABLE my_big_table;
CREATE TABLE my_big_table (a number, my_meta varchar2(30) not null);
INSERT INTO my_big_table (a, my_meta) SELECT rownum, 'GARBAGE' FROM dual CONNECT BY rownum <= 100000;
-- Drop the my_meta column and replace it with one having a default value
ALTER TABLE my_big_table DROP COLUMN my_meta;
ALTER TABLE my_big_table ADD my_meta varchar2(30) default 'INITIAL_VAL_FOR_TABLE' not null;
-- Look at my table -- you will see every row has your initial value
SELECT * FROM my_big_table;
-- Update some data
update my_big_table set my_meta = 'UPDATED_VALUE' WHERE a <= 15;
-- Look at my table -- you will see every row has your initial value except the first 15.
SELECT * FROM my_big_table order by a;