楼主: 幻雪青枫

3亿条数据的一个表插入新字段,并赋予默认值,如何做

[复制链接]
论坛徽章:
1
2012新春纪念徽章
日期:2012-01-04 11:58:44
21#
 楼主| 发表于 2012-2-26 21:02 | 只看该作者
robinxia 发表于 2012-2-26 12:59
1.create  table test_bak as select a.*,default_value as col1,default_val as col2 from test a;
2.ren ...

恩,这个方法确实是大家推荐的一种方法,只是我测试了一下需要creaTE INDEX 和constraint,不知道其它依赖对象如存储过程等时候会受到影响等?

使用道具 举报

回复
论坛徽章:
1
2012新春纪念徽章
日期:2012-01-04 11:58:44
22#
 楼主| 发表于 2012-2-26 21:29 | 只看该作者
robinxia 发表于 2012-2-26 12:59
1.create  table test_bak as select a.*,default_value as col1,default_val as col2 from test a;
2.ren ...

恩,这种方法,我做了一个300W数据的测试,还不错,只是需要create index 和constraints,不知道会不会对依赖此表的其它对象产生影响

使用道具 举报

回复
论坛徽章:
2
数据库板块每日发贴之星
日期:2009-07-28 01:01:022013年新春福章
日期:2013-02-25 14:51:24
23#
发表于 2012-2-27 17:32 | 只看该作者
两天前刚做了测试,alter 加默认值太慢了。 create table t as select * from t2 快

使用道具 举报

回复
论坛徽章:
6
2012新春纪念徽章
日期:2012-01-04 11:58:44灰彻蛋
日期:2012-02-17 15:04:17灰彻蛋
日期:2012-06-13 18:48:14双黄蛋
日期:2012-06-14 14:32:02奥运会纪念徽章:自行车
日期:2012-10-12 16:41:04双黄蛋
日期:2013-03-19 11:24:24
24#
发表于 2012-2-27 18:02 | 只看该作者
altert table test add a int;  先加字段
alter table test modify a default xx;再加默认值,现在加的默认值只对以后的记录有效
update test set a=xx ,b= xxx  where xxx; commit; 分批操作,将表里的记录更新为默认值

使用道具 举报

回复
论坛徽章:
9
生肖徽章2007版:羊
日期:2009-08-24 09:30:46ITPUB9周年纪念徽章
日期:2010-10-08 09:32:252011新春纪念徽章
日期:2011-02-18 11:42:49SQL大赛参与纪念
日期:2011-04-13 12:08:17ITPUB十周年纪念徽章
日期:2011-11-01 16:23:262012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB 11周年纪念徽章
日期:2012-10-09 18:07:31奥运纪念徽章
日期:2012-12-06 09:21:402013年新春福章
日期:2013-02-25 14:51:24
25#
发表于 2012-2-27 18:28 | 只看该作者
-- 个人建议:
---------------------------------------------------------------------------------------------------------------------------------------
-- *1. 如果原表有主键,可以新建一张表test2(注意表的其他字段应该和test1完全一致,最好用select dbms_metadata.get_ddl('TABLE','TEST) from dual 得到的代码去修改好后,执行创建test2表,
       另外,最好用分区表:如果主键是日期类型,可考虑按月分区;如果主键是int类型,可以考虑用范围分区);
--     其中test2表只比test1表多 colu1、colu2 两个字段,其他字段(包括数据类型、精确度、默认值)应该完全一致,还应该考虑表空间的存放问题;
--     如果原表(test表)有比较频繁的DML操作,则在test2上创建一个触发器用以与test同步其增、删、改操作(在触发器中注意多考虑colu1、colu2 两个字段的更新问题)
--     test2表创建好,触发器创建好后,就可以考虑往test2表中插入数据(可采用主键循环插入,例如:如果主键是日期类型,我可以按月来循环操作;如果主键是int类型,我可以按范围(例如,每次插入10万,循环结束后一次提交)循环插入)

-- *2. 如果原表没有主键,可以新建一张表test2(注意表的其他字段应该和test1完全一致,最好用select dbms_metadata.get_ddl('TABLE','TEST) from dual 得到的代码去修改好后,执行创建test2表,
       另外,最好用分区表:如果主键是日期类型,可考虑按月分区;如果主键是int类型,可以考虑用范围分区);
--     其中test2表比test1表多 colu1、colu2、rowid三个字段,其中rowid字段用来存放test表中的rowid,其他字段(包括数据类型、精确度、默认值)应该完全一致,还应该考虑表空间的存放问题;
--     如果原表(test表)有比较频繁的DML操作,则在test2上创建一个触发器用以与test同步(用rowid同步)其增、删、改操作(在触发器中注意多考虑colu1、colu2 两个字段的更新问题)
--     test2表创建好,触发器创建好后,就可以考虑往test2表中插入数据(可采用主键循环插入,例如:如果主键是日期类型,我可以按月来循环操作;如果主键是int类型,我可以按范围(例如,每次插入10万,循环结束后一次提交)循环插入)

使用道具 举报

回复
论坛徽章:
9
生肖徽章2007版:羊
日期:2009-08-24 09:30:46ITPUB9周年纪念徽章
日期:2010-10-08 09:32:252011新春纪念徽章
日期:2011-02-18 11:42:49SQL大赛参与纪念
日期:2011-04-13 12:08:17ITPUB十周年纪念徽章
日期:2011-11-01 16:23:262012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB 11周年纪念徽章
日期:2012-10-09 18:07:31奥运纪念徽章
日期:2012-12-06 09:21:402013年新春福章
日期:2013-02-25 14:51:24
26#
发表于 2012-2-27 19:02 | 只看该作者
-- 个人建议:
---------------------------------------------------------------------------------------------------------------------------------------
-- *1. 如果原表有主键,可以新建一张表test2(注意表的其他字段应该和test1完全一致,最好用select dbms_metadata.get_ddl('TABLE','TEST) from dual 得到的代码去修改好后,执行创建test2表,
       另外,最好用分区表:如果主键是日期类型,可考虑按月分区;如果主键是int类型,可以考虑用范围分区);
--     其中test2表只比test1表多 colu1、colu2 两个字段,其他字段(包括数据类型、精确度、默认值)应该完全一致,还应该考虑表空间的存放问题;
--     如果原表(test表)有比较频繁的DML操作,则在test2上创建一个触发器用以与test同步其增、删、改操作(在触发器中注意多考虑colu1、colu2 两个字段的更新问题)
--     test2表创建好,触发器创建好后,就可以考虑往test2表中插入数据(可采用主键循环插入,例如:如果主键是日期类型,我可以按月来循环操作;如果主键是int类型,我可以按范围(例如,每次插入10万,循环结束后一次提交)循环插入)
--     数据插入好后,就可以删除test,然后重命名test2为test (删除及重命名表操作最好封装到一个事务里,这样才不会影响你 的业务)

-- *2. 如果原表没有主键,可以新建一张表test2(注意表的其他字段应该和test1完全一致,最好用select dbms_metadata.get_ddl('TABLE','TEST) from dual 得到的代码去修改好后,执行创建test2表,
       另外,最好用分区表:如果主键是日期类型,可考虑按月分区;如果主键是int类型,可以考虑用范围分区);
--     其中test2表比test1表多 colu1、colu2、rowid三个字段,其中rowid字段用来存放test表中的rowid,其他字段(包括数据类型、精确度、默认值)应该完全一致,还应该考虑表空间的存放问题;
--     如果原表(test表)有比较频繁的DML操作,则在test2上创建一个触发器用以与test同步(用rowid同步)其增、删、改操作(在触发器中注意多考虑colu1、colu2 两个字段的更新问题)
--     test2表创建好,触发器创建好后,就可以考虑往test2表中插入数据(可采用主键循环插入,例如:如果主键是日期类型,我可以按月来循环操作;如果主键是int类型,我可以按范围(例如,每次插入10万,循环结束后一次提交)循环插入)
--     数据插入好后,就可以删除test,然后重命名test2为test (删除及重命名表操作最好封装到一个事务里,这样才不会影响你 的业务)

-- 例如:如果原表(没有主键)
-- 原表:
create table test(
  id number(18,0),
  uname varchar2(20)
);

create table test2(
  rowids rowid,
  id number(18,0),
  uname varchar2(20),
  colu1 varchar2(20) default 'chn' not null,
  colu2 number(18,0) default 2222 not null
);

CREATE OR REPLACE TRIGGER test_trg
AFTER INSERT OR UPDATE OR DELETE ON test
FOR EACH ROW
BEGIN
  IF INSERTING THEN
  BEGIN
    INSERT INTO test2(rowids,id,uname,colu1,colu2)
    VALUES(:NEW.rowid,:NEW.id,:NEW.uname,'chn',2222);
  END;
  ELSIF UPDATING THEN
  BEGIN
    UPDATE test2 SET rowids=:NEW.rowid,id=:NEW.id,uname=:NEW.uname WHERE rowids=:OLD.rowid;
  END;
  ELSE
  BEGIN
    DELETE FROM test2 WHERE rowids=:OLD.rowid;
  END;
  END IF;
END;
/

-- 测试:
-- 单行插入操作测试:
INSERT INTO test(id,uname) values(1,'lym1');
INSERT INTO test(id,uname) values(2,'lym2');
INSERT INTO test(id,uname) values(3,'lym3');
INSERT INTO test(id,uname) values(4,'lym4');
INSERT INTO test(id,uname) values(5,'lym5');
COMMIT;

SELECT * FROM test;
SELECT * FROM test2;

-- 多行插入操作测试:
INSERT INTO test(id,uname)
SELECT 6, 'zct2' FROM dual
UNION ALL
SELECT 7, 'hqg3' FROM dual;
COMMIT;

-- 单行更新操作测试:
UPDATE test set uname='tyg888' where id=1;
COMMIT;

SELECT * FROM test;
SELECT * FROM test2;

-- 单行删除操作测试:
delete from test where id=2;
COMMIT;

-- 以上测试均没问题

-- 然后同步两表的数据(最好用 where 条件循环控制,如我上面所说的):用存储过程 merge into ......
-- 例如(今天已经太晚,暂略):

使用道具 举报

回复
论坛徽章:
0
27#
发表于 2012-2-27 19:20 | 只看该作者
create table t as select * from t2
主要生成数据和创建索引耗的时间长一点。
还有就是要指定 nologing的方式

使用道具 举报

回复
论坛徽章:
1
2012新春纪念徽章
日期:2012-01-04 11:58:44
28#
 楼主| 发表于 2012-2-27 20:20 | 只看该作者
lucyne 发表于 2012-2-27 18:02
altert table test add a int;  先加字段
alter table test modify a default xx;再加默认值,现在加的默 ...

我在自己的本子上测试update貌似时间也不短

使用道具 举报

回复
论坛徽章:
1
2012新春纪念徽章
日期:2012-01-04 11:58:44
29#
 楼主| 发表于 2012-2-27 20:21 | 只看该作者
lxpbs8851 发表于 2012-2-27 19:20
create table t as select * from t2
主要生成数据和创建索引耗的时间长一点。
还有就是要指定 nologing ...

都提到需要重建索引,为什么没人提重新加约束呢?

使用道具 举报

回复
论坛徽章:
1
2012新春纪念徽章
日期:2012-01-04 11:58:44
30#
 楼主| 发表于 2012-2-27 20:23 | 只看该作者
luoyoumou 发表于 2012-2-27 19:02
-- 个人建议:
------------------------------------------------------------------------------------- ...

哈哈,写了这么多,我先仔细看看

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表