1、说明
某些物化视图日志由于客户端物化视图刷新地不是很及时,导致物化视图日志表膨胀地非常厉害,但实际日志表里的数据又不是很多。一般物化视图日志表上没有索引,刷新物化视图需要对物化视图日志进行全表扫描,所以考虑到客户端的刷新速度和空间容量回收等问题,对于这种膨胀比较厉害的物化视图日志,需要进行收缩物化视图日志表其实是一张普通表,所以对它进行收缩的方法也比较多,但这些方法有些会影响物化视图日志的基表(也就是业务表)上的业务,有些可以在不影响基表业务的情况下收缩,可以根据各自的情况选择不同的方法
2、前期准备工作
【线下操作物化视图日志表收缩】 远程数据库建立堆组织表 CREATE TABLE T_600_RESULTS ( COL1 NUMBER , COL2 VARCHAR2(10 CHAR), COL3 VARCHAR2(10CHAR) ) SEGMENT CREATION IMMEDIATE TABLESPACE ETL_NEW NOLOGGING ; --添加主键约束 ALTER TABLE T_600_RESULTS ADD CONSTRAINTS PK_T_600_RESULTS PRIMARY KEY(COL1) USING INDEX TABLESPACE ETL_INDEX; --插入测试数据 INSERT INTO T_600_RESULTS NOLOGGING SELECT ROWNUM"COL1", DBMS_RANDOM.STRING('X', 8) "COL2", DBMS_RANDOM.STRING('Q', 8) "COL3" FROM DUAL CONNECT BY ROWNUM <= 1000; --远程端创建物化视图日志 CREATE MATERIALIZED VIEW LOG ON T_600_RESULTS WITH PRIMARY KEY; --本地创建物化视图 CREATE MATERIALIZED VIEW MV_600_RESULTS NOLOGGING NOPARALLEL TABLESPACE BI REFRESH FAST ON DEMAND WITH PRIMARY KEY START WITH SYSDATE NEXT SYSDATE +INTERVAL'1'MINUTE ENABLE QUERY REWRITE AS SELECT * FROM T_600_RESULTS@LINK_ETL; 核实数据字典内容 --查询物化视图相关信息 SELECT T.MVIEW_NAME, T.CONTAINER_NAME, T.MASTER_LINK, T.REWRITE_ENABLED, T.REFRESH_METHOD, T.BUILD_MODE, T.FAST_REFRESHABLE, T.LAST_REFRESH_DATE FROM USER_MVIEWS T WHERE T.MVIEW_NAME = Q'{MV_600_RESULTS}' --远程数据库执行 SELECT * FROM USER_TABLES WHERE INSTR(TABLE_NAME,'MLOG$_T_600_RESULTS',1)>0 --本地查询 SELECT NAME,MASTER,LAST_REFRESH FROM USER_MVIEW_REFRESH_TIMES WHERE LAST_REFRESH >=DATE'2017-05-08' --对堆组织表做插入操作 DECLARE TYPE T_TAB IS TABLE OF T_600_RESULTS%ROWTYPE; L_TAB T_TAB := T_TAB(); L_ERROR_COUNT NUMBER; EX_DML_ERRORS EXCEPTION; PRAGMA EXCEPTION_INIT(EX_DML_ERRORS, -24381); BEGIN FOR I IN 1001 .. 1500 LOOP L_TAB.EXTEND; L_TAB(L_TAB.LAST).COL1 := I; L_TAB(L_TAB.LAST).COL2 := DBMS_RANDOM.string('W',8); L_TAB(L_TAB.LAST).COL3 := DBMS_RANDOM.string('A',8); END LOOP; -- Perform a bulk operation. BEGIN FORALL I IN L_TAB.FIRST .. L_TAB.LAST SAVE EXCEPTIONS INSERT INTO T_600_RESULTS VALUES L_TAB (I); EXCEPTION WHEN EX_DML_ERRORS THEN L_ERROR_COUNT := SQL%BULK_EXCEPTIONS.COUNT; DBMS_OUTPUT.PUT_LINE('Number of failures: ' || L_ERROR_COUNT); FOR I IN 1 .. L_ERROR_COUNT LOOP DBMS_OUTPUT.PUT_LINE('Error: ' || I || ' Array Index: ' || SQL%BULK_EXCEPTIONS(I) .ERROR_INDEX || ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(I).ERROR_CODE)); END LOOP; END; END; --对物化视图刷新基表强制独占锁 LOCK TABLE T_600_RESULTS IN EXCLUSIVE MODE; --创建物化视图临时日志表 CREATE TABLE MV_TEMP_600_RESULTS NOLOGGING AS SELECT * FROM MLOG$_T_600_RESULTS --清理物化视图日志表 TRUNCATE TABLE MLOG$_T_600_RESULTS --将临时日志表内容重新同步到物化视图日志表 INSERT INTO MLOG$_T_600_RESULTS SELECT * FROM MV_TEMP_600_RESULTS --释放锁资源,执行回滚操作 ROLLBACK;
复制
3、线上操作物化视图日志表收缩
BEGIN DBMS_REDEFINITION.CAN_REDEF_TABLE(UNAME => 'ETL', TNAME => 'MLOG$_T_600_RESULTS', OPTIONS_FLAG => DBMS_REDEFINITION.cons_use_rowid); END; --创建在线重定义临时表 DROP TABLE MV_TEMP_600_RESULTS CASCADE CONSTRAINTS; create table MV_TEMP_600_RESULTS ( col1 NUMBER, snaptime$$ DATE, dmltype$$ VARCHAR2(1), old_new$$ VARCHAR2(1), change_vector$$ RAW(255), xid$$ NUMBER ) SEGMENT CREATION IMMEDIATE tablespace ETL; --开始在线重定义操作 BEGIN DBMS_REDEFINITION.START_REDEF_TABLE(UNAME => 'ETL', ORIG_TABLE => 'MLOG$_T_600_RESULTS', INT_TABLE => 'MV_TEMP_600_RESULTS', OPTIONS_FLAG => DBMS_REDEFINITION.CONS_USE_ROWID); END; --复制依赖对象 即:主键、索引、约束、check等 DECLARE NUM_ERRORS PLS_INTEGER; BEGIN DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(UNAME => 'ETL', ORIG_TABLE => 'MLOG$_T_600_RESULTS', INT_TABLE => 'MV_TEMP_600_RESULTS', COPY_INDEXES => DBMS_REDEFINITION.CONS_ORIG_PARAMS, COPY_TRIGGERS => TRUE, COPY_CONSTRAINTS => FALSE, COPY_PRIVILEGES => TRUE, IGNORE_ERRORS => FALSE, NUM_ERRORS => NUM_ERRORS, COPY_STATISTICS => TRUE); END; --开始在线重定义同步操作 BEGIN DBMS_REDEFINITION.SYNC_INTERIM_TABLE(UNAME => 'ETL', ORIG_TABLE => 'MLOG$_T_600_RESULTS', INT_TABLE => 'MV_TEMP_600_RESULTS'); END; --完成在线重定义操作 BEGIN DBMS_REDEFINITION.FINISH_REDEF_TABLE(UNAME => 'ETL', ORIG_TABLE => 'MLOG$_T_600_RESULTS', INT_TABLE => 'MV_TEMP_600_RESULTS'); END; 这里使用rowid方式,重定义完的表上会多出一个隐藏字段,从10.2开始M_ROW$$的隐藏列会被命名为SYS_%DATE%的形式,且默认即为unused状态: SELECT * FROM DBA_UNUSED_COL_TABS WHERE TABLE_NAME = Q'{MLOG$_T_600_RESULTS}' -- ALTER TABLE MLOG$_T_600_RESULTS DROP UNUSED COLUMNS;
复制
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
大佬,您好,这个在线的重定义,需要创建一张和mlog$一样的临时表,想问下,这个临时表的作用是什么,是为了迁移原日志表中的数据吗
4年前

评论
实操性很强。作者有没有遇到过 通过dblink 刷新物化视图时,少两条数据,但是在后几次的刷新时。又将两条数据刷了过来。这种现象时不时的出现。(基于主键的快速增量刷新)
4年前

评论
第一次发表文章,实际工作中遇到的技术干货,有不对的地方请指教~
4年前

评论
相关阅读
【专家有话说第五期】在不同年龄段,DBA应该怎样规划自己的职业发展?
墨天轮编辑部
1252次阅读
2025-03-13 11:40:53
Oracle RAC ASM 磁盘组满了,无法扩容怎么在线处理?
Lucifer三思而后行
758次阅读
2025-03-17 11:33:53
Oracle+Deepseek+Dify 实现数据库数据实时分析
bicewow
666次阅读
2025-03-06 09:41:49
【ORACLE】ORACLE19C在19.13版本前的一个严重BUG-24761824
DarkAthena
556次阅读
2025-03-04 14:33:31
Oracle避坑指南|同名表导出难题:如何精准排除指定用户下的表?
szrsu
506次阅读
2025-03-05 00:42:34
2月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
448次阅读
2025-03-13 14:38:19
Ogg23ai高手必看-MySQL Innodb Cluster跟oracle的亲密接触
曹海峰
441次阅读
2025-03-04 21:56:13
【ORACLE】char类型和sql优化器发生的“错误”反应
DarkAthena
402次阅读
2025-03-04 23:05:01
什么,oracle 主机用户被删了?原来是虚惊一场!
Lucifer三思而后行
399次阅读
2025-03-03 21:12:09
Oracle 如何修改 db_unique_name?强迫症福音!
Lucifer三思而后行
337次阅读
2025-03-12 21:27:56