首页 > 数据库 > Oracle > Oracle在线重定义操作一张近300G的表的实验
author:zy
目录:
说明:本文相关表名、库名已过敏
通过本实验,证明重定义是可以操作大表的。其原理也就是通过insert /*+ BYPASS_RECURSIVE_CHECK APPEND SKIP_UNQ_UNUSABLE_IDX */ 这种不会产生undo
重定义需要的数据表空间、TEMP表空间、归档空间较多,在重定义之前需要准备充沛
正确的重定义顺序为:
之前我有对一张70G表的,重定义失败。当时花在start_redef_table为60分钟,但花在sync_interim_table确30分钟还没好,后来貌似是ctrl+c导致报错了(PS:当时知识欠火候,应该在等了30分钟没好的情况下,分析后台在做些什么样的操作)。
另外一位同事有对一张276G的表重定义。等了2个小时没响应就取消了。卡在start_redef_table这一步
苏说:估计会报TEMP表空间不足,我记得上次 是最后一步报错的,就差一点就成功了 如果不是报temp不足的话
高说:当时追踪后台情况是:数据已经追平,后台在做一些排序的操作。占用temp,估计是一些内部处理。
事后对当时的建议操作:
|
高说(最新):之前的操作是先对中间表建好索引,然后在执行start,结果start花了2小时间还没成功
前言:现在预付卡有张240G的表需要分表,考虑到不好停业务的情形,但以前又有大表重定义失败的案例。特在客户端ogg库做下实验(该库即将下线,因此没业务但资源充沛)
我们现在要操作的这张表:
查看表空间:
|
|
TABLESPACE_NAME |
共G |
已用G |
已用% |
剩余G |
AUTOEXTENSIBLE |
increment_by(M) |
|
1 |
IDX_MEPF_B |
1020 |
313.93 |
30.78 |
706.07 |
NO |
0 |
|
7 |
TEMP |
122 |
0 |
0 |
122 |
YES |
0.625 |
|
9 |
UNDOTBS1 |
48 |
0.82 |
1.71 |
47.18 |
YES |
5 |
我们只关心3类指标:TEMP、UNDOTBS1、和用户表空间(IDX_MEPF_B)
另外本库是一张没人使用的库
查看数据库归档,归档目录空间充裕
ok,相关的检查已经到位,符合实验
create table test_REDEFINE
(
dcoper_id NUMBER(10) not null,
party_group VARCHAR2(2),
serv_infname VARCHAR2(50),
serv_gwname VARCHAR2(128),
pfaddr VARCHAR2(256),
obj_code VARCHAR2(50),
obj_value VARCHAR2(500),
obj_code2 VARCHAR2(50),
obj_value2 VARCHAR2(500),
ret_code VARCHAR2(10),
ret_info VARCHAR2(512),
begin_date DATE not null,
end_date DATE,
stat CHAR(3) not null
) tablespace IDX_MEPF_B;
EXEC dbms_redefinition.can_redef_table(user, 'REDEFINE'); --pass
2016/3/25 10:34:30开始操作
[pcloud@khd-ctg-122-23 zy]$ vi cmd.sql
begin
dbms_redefinition.start_redef_table(uname => 'ZY',
orig_table => 'REDEFINE',
int_table => 'test_REDEFINE');
end;
/
sqlplus ZY/Zhouyun@172.17.1.1/orcl @cmd.sql&
这一步执行时间较长。
20160325 12:22执行sync
|
[pcloud@khd-ctg-122-23 zy]$ vi cmd2.sql begin dbms_redefinition.sync_interim_table(uname => 'ZY', orig_table => 'REDEFINE', int_table => 'TEST_REDEFINE'); end; /
dbms_redefinition.sync_interim_table(uname=>'MEPF_DEV',orig_table=>'T_GWM_PKTCOLL',int_table=>'TEMP_T_GWM_PKTCOLL'); |
sqlplus ZY/Zhouyun@172.17.1.1/orcl @cmd2.sql&
25-3月 -16 01.02.38.546 下午 sync结束
20160325 13:08 建主键索引
|
[pcloud@khd-ctg-122-23 zy]$ vi cmd3.sql create /*+parallel(16)*/ unique index PK_T_REDEFINE_TMP_812 on test_REDEFINE(DCOPER_ID, BEGIN_DATE) tablespace IDX_MEPF_B;
alter table test_REDEFINE add constraint PK_T_REDEFINE_TMP_812 primary key (DCOPER_ID, BEGIN_DATE) using index tablespace IDX_MEPF_B;
[pcloud@khd-ctg-122-23 zy]$ sqlplus ZY/Zhouyun@172.17.1.1/orcl @cmd3.sql & |
25-3月 -16 01.36.14.248 下午 索引建完
20160325 1349,在次模拟sync,insert100 update10条。结果是瞬间就完了
20160325 1353 执行finish,瞬间完成
2016/3/25 10:34:30开始操作
select * from util_session where sid in(1713) --1713,47975
2016/3/25 10:35语句执行完成
20160325 12:22执行sync
25-3月-16 01.02.38.546 下午 sync结束
20160325 13:08 建主键索引
后台抓到的执行的语句
2016/3/25 10:39 现在这个点在执行以下语句,重定义是不占undo的
等待事件
|
Sql_id: fuptcd3hsm5w6 INSERT /*+ BYPASS_RECURSIVE_CHECK APPEND SKIP_UNQ_UNUSABLE_IDX */ INTO "ZY"."TEST_REDEFINE" ("DCOPER_ID", "PARTY_GROUP", "SERV_INFNAME", "SERV_GWNAME", "PFADDR", "OBJ_CODE", "OBJ_VALUE", "OBJ_CODE2", "OBJ_VALUE2", "RET_CODE", "RET_INFO", "BEGIN_DATE", "END_DATE", "STAT") SELECT "REDEFINE"."DCOPER_ID", "REDEFINE"."PARTY_GROUP", "REDEFINE"."SERV_INFNAME", "REDEFINE"."SERV_GWNAME", "REDEFINE"."PFADDR", "REDEFINE"."OBJ_CODE", "REDEFINE"."OBJ_VALUE", "REDEFINE"."OBJ_CODE2", "REDEFINE"."OBJ_VALUE2", "REDEFINE"."RET_CODE", "REDEFINE"."RET_INFO", "REDEFINE"."BEGIN_DATE", "REDEFINE"."END_DATE", "REDEFINE"."STAT" FROM "ZY"."REDEFINE" "REDEFINE" |
2016/3/25 11:18 还是在执行这条,等待事件direct path write
25-3月 -16 11.50.23.771 上午语句执行完成,start过程执行完成了
20160325 1228 执行sync捕获到的后台代码
|
Sql_id: 35f64tfcknmp6 ,这一步是在删除中间表含mlog$的数据,mlog$是我们更新数据的记录表。 因为all_summap记录了scn号,所以这个操作应该只是检查下,其它是没有数据删除的。但由于TEST_REDEFINE没建索引,导致这一步耗时了20分钟
DELETE FROM "ZY"."TEST_REDEFINE" SNAP$ WHERE ("DCOPER_ID", "BEGIN_DATE") IN (SELECT DISTINCT MLOG$."DCOPER_ID", MLOG$."BEGIN_DATE" FROM "ZY"."MLOG$_REDEFINE" MLOG$, ALL_SUMMAP MAP$ WHERE MLOG$.XID$$ = MAP$.XID AND MAP$.COMMIT_SCN > :1 AND MAP$.COMMIT_SCN <= :2 AND ("DMLTYPE$$" != 'I'))
|
20160325 1233
居然要15分钟,我这边更改的数据才
100条insert 10条update (已提交)
10条update(未提交)
为什么会这么慢呢?我们看语句是<("DCOPER_ID", "BEGIN_DATE") IN>,会不会是缺少索引才这么慢的。那么下一步,我们建好索引在同步下
20160325 1245 语句变成了merge操作,这是实际的更新数据了
|
Sqlid: 58h1udfyqy0jb /* MV_REFRESH (MRG) */ MERGE INTO "ZY"."TEST_REDEFINE" "SNA$" USING (SELECT CURRENT$."DCOPER_ID", CURRENT$."PARTY_GROUP", CURRENT$."SERV_INFNAME", CURRENT$."SERV_GWNAME", CURRENT$."PFADDR", CURRENT$."OBJ_CODE", CURRENT$."OBJ_VALUE", CURRENT$."OBJ_CODE2", CURRENT$."OBJ_VALUE2", CURRENT$."RET_CODE", CURRENT$."RET_INFO", CURRENT$."BEGIN_DATE", CURRENT$."END_DATE", CURRENT$."STAT" FROM (SELECT "REDEFINE"."DCOPER_ID" "DCOPER_ID", "REDEFINE"."PARTY_GROUP" "PARTY_GROUP", "REDEFINE"."SERV_INFNAME" "SERV_INFNAME", "REDEFINE"."SERV_GWNAME" "SERV_GWNAME", "REDEFINE"."PFADDR" "PFADDR", "REDEFINE"."OBJ_CODE" "OBJ_CODE", "REDEFINE"."OBJ_VALUE" "OBJ_VALUE", "REDEFINE"."OBJ_CODE2" "OBJ_CODE2", "REDEFINE"."OBJ_VALUE2" "OBJ_VALUE2", "REDEFINE"."RET_CODE" "RET_CODE", "REDEFINE"."RET_INFO" "RET_INFO", "REDEFINE"."BEGIN_DATE" "BEGIN_DATE", "REDEFINE"."END_DATE" "END_DATE", "REDEFINE"."STAT" "STAT" FROM "ZY"."REDEFINE" "REDEFINE") CURRENT$, (SELECT DISTINCT MLOG$."DCOPER_ID", MLOG$."BEGIN_DATE" FROM "ZY"."MLOG$_REDEFINE" MLOG$, ALL_SUMMAP MAP$ WHERE MLOG$.XID$$ = MAP$.XID --xid上有建索引 AND MAP$.COMMIT_SCN > :1 AND MAP$.COMMIT_SCN <= :2 AND ("DMLTYPE$$" != 'D')) LOG$ WHERE CURRENT$."DCOPER_ID" = LOG$."DCOPER_ID" AND CURRENT$."BEGIN_DATE" = LOG$."BEGIN_DATE") "AV$" ON ("SNA$"."DCOPER_ID" = "AV$"."DCOPER_ID" AND "SNA$"."BEGIN_DATE" = "AV$"."BEGIN_DATE") WHEN MATCHED THEN UPDATE SET "SNA$"."DCOPER_ID" = "AV$"."DCOPER_ID", "SNA$"."PARTY_GROUP" = "AV$"."PARTY_GROUP", "SNA$"."SERV_INFNAME" = "AV$"."SERV_INFNAME", "SNA$"."SERV_GWNAME" = "AV$"."SERV_GWNAME", "SNA$"."PFADDR" = "AV$"."PFADDR", "SNA$"."OBJ_CODE" = "AV$"."OBJ_CODE", "SNA$"."OBJ_VALUE" = "AV$"."OBJ_VALUE", "SNA$"."OBJ_CODE2" = "AV$"."OBJ_CODE2", "SNA$"."OBJ_VALUE2" = "AV$"."OBJ_VALUE2", "SNA$"."RET_CODE" = "AV$"."RET_CODE", "SNA$"."RET_INFO" = "AV$"."RET_INFO", "SNA$"."BEGIN_DATE" = "AV$"."BEGIN_DATE", "SNA$"."END_DATE" = "AV$"."END_DATE", "SNA$"."STAT" = "AV$"."STAT" WHEN NOT MATCHED THEN INSERT (SNA$."DCOPER_ID", SNA$."PARTY_GROUP", SNA$."SERV_INFNAME", SNA$."SERV_GWNAME", SNA$."PFADDR", SNA$."OBJ_CODE", SNA$."OBJ_VALUE", SNA$."OBJ_CODE2", SNA$."OBJ_VALUE2", SNA$."RET_CODE", SNA$."RET_INFO", SNA$."BEGIN_DATE", SNA$."END_DATE", SNA$."STAT") VALUES (AV$."DCOPER_ID", AV$."PARTY_GROUP", AV$."SERV_INFNAME", AV$."SERV_GWNAME", AV$."PFADDR", AV$."OBJ_CODE", AV$."OBJ_VALUE", AV$."OBJ_CODE2", AV$."OBJ_VALUE2", AV$."RET_CODE", AV$."RET_INFO", AV$."BEGIN_DATE", AV$."END_DATE", AV$."STAT") |
表空间
2016/3/25 10:43表空间:
数据文件占用了,但temp还没动
2016/3/25 11:21 temp和undo依旧没有占用
2016/3/25 11:50 语句执行完成
20160325 1318 建索引这步,temp吃掉了20g来了,索引是66g大小(建索引对temp要求较大)
1322 表空间达到了47g,我怀疑分析表local分区大小会小点,按分区来的
1324 temp
1326 temp已不在增加,同时idx_mepf_b开始减少空间,说明数据正temp读取到表空间
这步可以通过并发减少及等待事件可以看出
1328 索引数据落盘中
1333
1337 索引建完
2016/3/25 10:44临时表空间持续在增加,现在是花了10分钟,大概完成了1/10多,预计在100分之内完成
2016/3/25 11:01
2016/3/25 11:17
20160325 11:25
20160325 11:50
20160325 1330 此时在建索引,但segment查不到索引的大小变化
2016/3/25 10:35:30
我们通过点击TEST_REDEFINE,可以看到TEST_REDEFINE其实是张物化视图,映射到了REDEFINE
|
CREATE MATERIALIZED VIEW TEST_REDEFINE ON PREBUILT TABLE REFRESH FAST ON DEMAND AS SELECT "REDEFINE"."DCOPER_ID" "DCOPER_ID","REDEFINE"."PARTY_GROUP" "PARTY_GROUP","REDEFINE"."SERV_INFNAME" "SERV_INFNAME","REDEFINE"."SERV_GWNAME" "SERV_GWNAME","REDEFINE"."PFADDR" "PFADDR","REDEFINE"."OBJ_CODE" "OBJ_CODE","REDEFINE"."OBJ_VALUE" "OBJ_VALUE","REDEFINE"."OBJ_CODE2" "OBJ_CODE2","REDEFINE"."OBJ_VALUE2" "OBJ_VALUE2","REDEFINE"."RET_CODE" "RET_CODE","REDEFINE"."RET_INFO" "RET_INFO","REDEFINE"."BEGIN_DATE" "BEGIN_DATE","REDEFINE"."END_DATE" "END_DATE","REDEFINE"."STAT" "STAT" FROM "ZY"."REDEFINE" "REDEFINE"; |
但在dba_objects中查看到的定义仍是table,怀疑他这种定义只是个临时的物化视图,字典无法查到
另外,我们抓到一张表MLOG$_的表
select * from dba_objects where object_name like '%MLOG$_REDEFINE%';
|
|
OWNER |
OBJECT_NAME |
SUBOBJECT_NAME |
OBJECT_ID |
DATA_OBJECT_ID |
OBJECT_TYPE |
CREATED |
LAST_DDL_TIME |
TIMESTAMP |
STATUS |
TEMPORARY |
GENERATED |
SECONDARY |
NAMESPACE |
EDITION_NAME |
|
1 |
ZY |
MLOG$_REDEFINE |
|
173082 |
173082 |
TABLE |
2016/3/25 10:34:31 |
2016/3/25 10:34:31 |
2016-03-25:10:34:31 |
VALID |
N |
N |
N |
1 |
|
20160325 11:50
定义还是物化视图
20160325 1321 趁着在建索引,我们看下mlog$表,该表刚刚在sync后。数据已经清空了
2016/3/25 10:49
最新的归档,归档占用了61个g来了
2016/3/25 10:55
20160325 11:24
20160325 11:29
20160325 11:50 归档的占用差不多是一比一
模拟生产,对源表产生修改
20160325 11:44执行
insert into REDEFINE select * from T_REDEFINE_ogg where rownum<=100;
update REDEFINE partition(SYS_P1231) set obj_code2='zy test' where dcoper_id in(3874113719,
3874113721,
3874113731,
3874113733,
3874113736,
3874113741,
3874113744,
3874113755,
3874113756,
3874113757);
commit;
20160325 12:21执行,但不提交,查看数据是否会同步
事后补充:20160325 1255:通过查看mlog$,发现没有提交的数据没在这个表里,事后在没commit的情况下,查询中间表,数据也是没同步的
update REDEFINE partition(SYS_P1231) set obj_code2='zy test1' where dcoper_id in(3874113719,
3874113721,
3874113731,
3874113733,
3874113736,
3874113741,
3874113744,
3874113755,
3874113756,
3874113757);
20160325 12:49,我们查看mlog$表,发现刚刚commit更新的数据记录在了该表。由此可以肯定MLOG$表是记录执行期间变化的表。正好110条
1347 在建好索引后,在次模拟速度
|
insert into REDEFINE select dcoper_id, party_group, serv_infname, serv_gwname, pfaddr, obj_code, obj_value, obj_code2, obj_value2, ret_code, ret_info, begin_date, end_date, stat from (select t.*,rownum rn from T_REDEFINE_ogg t where rownum<=200) where rn>100;
update REDEFINE partition(SYS_P1231) set obj_code2='zy test1' where dcoper_id in(3874113719, 3874113721, 3874113731, 3874113733, 3874113736, 3874113741, 3874113744, 3874113755, 3874113756, 3874113757); |
通过本实验,证明重定义是可以操作大表的。其原理也就是通过insert /*+ BYPASS_RECURSIVE_CHECK APPEND SKIP_UNQ_UNUSABLE_IDX */ 这种不会产生undo
重定义需要的数据表空间、TEMP表空间、归档空间较多,在重定义之前需要准备充沛
正确的重定义顺序为:
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/30109892/viewspace-2063931/ ,如需转载,请注明出处,否则将追究法律责任。