ORACLE TABLE有大量记录,如果增加字段带default值需要很长时间

本文探讨了在Oracle数据库中向大型表添加字段的不同方法及其性能影响。对比了直接添加带有默认值的字段与分两步执行(先添加字段再设置默认值)的方法,并介绍了在不同Oracle版本中的表现差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

manpower.s_salary 375w記錄,需增加栏位add_sh number(7,2) default 0


1.先排除无人使用

SELECT P.SPID,s.STATUS,s.terminal,s.machine,s.program,s.osuser,s.CLIENT_INFO,s.LOGON_TIME

FROM V$SESSION S,V$ACCESS A,V$PROCESS P
WHERE S.SID=A.SID
  AND S.PADDR=P.ADDR

  AND A.OBJECT='S_SALARY'


2.alter table manpower.s_salary add (add_sh number(7,2) default 0);
需要时间21分钟。(中午下班时间执行)


分2步执行,效果显著提高

alter table manpower.s_salary add (add_sh number(7,2));
需要时间0.25秒。

alter table manpower.s_salary modify (add_sh number(7,2) default 0);

需要时间0.25秒。

oracle版本为10.2.05


还是有的:
1) 在ALTER sql中有带缺省值,ORACLE会直接刷新全部的记录。
2) 在ALTER sql中没有带缺省值,ORACLE只会影响到后来的记录。(明白快是有隐秘的秘诀)

在选择哪种方法时,要更加具体的情况来实施:是否有INDEX,是否在应用的高并发阶段,等等


------------------------------------------以下为转载http://yinzhihua2008.blog.163.com/blog/static/7943067201211241056654/----------------------------------

ORACLE数据表有很多数据如果增加字段需要很长时间  

关于创建的方式哪种更快,需要综合考虑,由于楼主的库是非归档模式的,所以估计是个测试库。
对于测试环境,楼主的两种加载数据的方式都可行,我测试环境没有那么大的表,只能拿一个有1500万行,1G大小的表测试了一下,采用数据泵方式用了5分钟(导出加导入),采用insert /*+append*/ 方式用时216秒(如果加载新增字段为not null,需要260秒),看似insert /*+append*/的效率更高一些;不过有几点要注意的:
1.在正式的生产环境,考虑到数据可恢复的问题,可能insert /*+append*/是不能被接受的
2.这两种方式目标表的默认值只对新插入的数据有效,而对导入自原表中的数据无效。
3.采用数据泵模式,新加的字段不能为not null
对于可以接受停机的生产库,为了保证数据的可恢复,建议采用数据泵或者直接路径加载的sql loader试试
但是,现在越来越多的oracle充当企业关键数据库,可能不会给予足够的停机时间,此时可以采用在线重定义等高可用方式。
或者,按照以下步骤:
1.在表上增加一个新字段,不带默认值,这个操作应该很快
alter table test add test number;
2.把此字段改为默认值,这样,以后插入的数据就包含默认值了,但是修改之前的字段值仍然为空
alter table test modify test default 88888888;
3.如果需要将修改前的默认值加入相关的历史数据,可以做一个批量更新的存储过程,定义比如每1000条一次commit,以减小生产库的压力。
4.更新完成后,可以将字段设置为not null模式
总之,在生产库的真实环境中(尤其是24X7库),有时候速度并不是唯一要考虑的因素,还要考虑数据的可恢复性,操作时对数据库的性能影响,以及停机时间,这就是为什么oracle会提供速度并不突出的在线重定义的原因。有时为了减轻对生产库的压力,我也会故意在循环插入、更新和删除的存储过程中加入延迟,以防治日志过于频繁的切换。
上述测试是基于10g的,在11g中,看来oracle已经意识到了这个问题,所以可以直接采用添加默认值的语法,这个更新应该时间很短,因为你查到以前数据上新加的字段上已经有默认值了,但是这是通过oracle内部函数计算后显示出来的,而不是真实存在于数据库中的,只有以后加入的数据,默认值才会真实插入数据库表中,所以11g中你可以使用下面语句:
alter table test add test number default 88888888 not null;


Oracle 数据库中新增字段,主要通过 `ALTER TABLE` 语句实现。新增字段的基本语法如下: ```sql ALTER TABLE 表名 ADD 字段字段类型 [默认] [约束条件]; ``` 例如,向名为 `STUDENT_INFO` 的表中添加一个 `ADDRESS` 字段字段类型为 `VARCHAR2(120)`,可以使用以下 SQL 语句: ```sql ALTER TABLE STUDENT_INFO ADD ADDRESS VARCHAR2(120); ``` 如果希望在新增字段的同时为其设置默认,可以使用 `DEFAULT` 关键字。例如,添加一个 `AGE` 字段,并设置默认为 `18`: ```sql ALTER TABLE STUDENT_INFO ADD AGE NUMBER(3) DEFAULT 18; ``` 此外,还可以为新增的字段添加注释。例如,为 `ADDRESS` 字段添加注释“地址”: ```sql COMMENT ON COLUMN STUDENT_INFO.ADDRESS IS '地址'; ``` 如果需要一次性为多个表新增字段,可以通过编写 PL/SQL 脚本实现。例如,为当前用户中所有表名称包含 `_OPT` 的表新增 `IMPORT_DATE` 字段,并添加注释“入库日期”[^5]: ```plsql DECLARE v_alter_sqlstr VARCHAR2(500); CURSOR c_result IS SELECT 'ALTER TABLE ' || t.OBJECT_NAME || ' ADD IMPORT_DATE DATE DEFAULT SYSDATE; COMMENT ON COLUMN ' || t.OBJECT_NAME || '.IMPORT_DATE IS ''入库日期'';' FROM user_objects t WHERE t.OBJECT_TYPE = 'TABLE' AND t.object_name LIKE '%_OPT'; v_result c_result%ROWTYPE; BEGIN OPEN c_result; LOOP FETCH c_result INTO v_result; EXIT WHEN c_result%NOTFOUND; v_alter_sqlstr := v_result.alter_sqlstr; DBMS_OUTPUT.PUT_LINE(v_alter_sqlstr); -- 执行修改 EXECUTE IMMEDIATE v_alter_sqlstr; END LOOP; CLOSE c_result; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('异常:' || 'SQLCODE:' || SQLCODE || ' SQLERRM : ' || SQLERRM); END; ``` 需要注意的是,Oracle 不支持在指定字段后新增字段的操作[^1]。如果需要调整字段顺序,通常需要通过创建新表并重新导入数据的方式来实现。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值