ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 包含LOB的物化视图快速刷新(三)

包含LOB的物化视图快速刷新(三)

原创 Linux操作系统 作者:yangtingkun 时间:2009-11-12 19:52:52 0 删除 编辑

以前写过一篇文章描述物化视图是否进行字段级的刷新。当时得出的结论是包含LOB字段的物化视图会进行字段级的刷新,但是这个结论是在9.2上得出的,最近测试发现,10g上的结果有所不同。

这篇文章研究10g以后版本当LOB对象超过32K时,物化视图如何刷新。

包含LOB的物化视图快速刷新:http://yangtingkun.itpub.net/post/468/493060

包含LOB的物化视图快速刷新(二):http://yangtingkun.itpub.net/post/468/493206

物化视图是否根据字段进行刷新(一):http://yangtingkun.itpub.net/post/468/201236

物化视图是否根据字段进行刷新(二):http://yangtingkun.itpub.net/post/468/201607

物化视图是否根据字段进行刷新(三):http://yangtingkun.itpub.net/post/468/203414

 

 

在上面一篇文章中测试发现,在10.2版本中,如果基表的LOB对象超过了4K,或者基表的LOB存储在行外,则物化视图视图刷新的时候对LOB更新了两次,下面将LOB字段的内容增加,使得LOB容量超过VARCHAR2类型的上限32K,再次运行刷新,并建立触发器,检查物化视图刷新时,LOB列被更新的次数。

SQL> SELECT * FROM V$VERSION;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE    10.2.0.3.0      Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production

SQL> CREATE TABLE T
  2  (
  3     ID NUMBER,
  4     NAME VARCHAR2(30),
  5     CONTENTS CLOB,
  6     CONSTRAINT PK_T PRIMARY KEY (ID)
  7  );

Table created.

SQL> CREATE MATERIALIZED VIEW LOG ON T;

Materialized view log created.

SQL> CREATE MATERIALIZED VIEW MV_T REFRESH FAST AS
  2  SELECT *
  3  FROM T;

Materialized view created.

SQL> DECLARE
  2     V_LOB CLOB;
  3     V_STR VARCHAR2(32767) := RPAD('A', 32767, 'A');
  4  BEGIN
  5     INSERT INTO T VALUES (1, 'TEST', EMPTY_CLOB) RETURN CONTENTS INTO V_LOB;
  6     FOR I IN 1..10 LOOP
  7             DBMS_LOB.WRITEAPPEND(V_LOB, LENGTH(V_STR), V_STR);
  8     END LOOP;
  9     COMMIT;
 10  END;
 11  /

PL/SQL procedure successfully completed.

SQL> CREATE OR REPLACE TRIGGER TRI_MV_T
  2  AFTER INSERT OR UPDATE OR DELETE ON MV_T
  3  FOR EACH ROW
  4  BEGIN
  5     DBMS_OUTPUT.PUT_LINE(DBMS_LOB.GETLENGTH(:NEW.CONTENTS));
  6  END;
  7  /

Trigger created.

SQL> SET SERVEROUT ON
SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
327670

PL/SQL procedure successfully completed.

SQL> UPDATE T
  2  SET NAME = 'ABC'
  3  WHERE ID = 1;

1 row updated.

SQL> COMMIT;

Commit complete.

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
327670

PL/SQL procedure successfully completed.

从触发器的工作状态看,物化视图的LOB字段只被更新了一次,即使只更新一次,也意味着10g版本的物化视图的刷新性能要比9.2的差,因为9.2只是根据需要决定是否对物化视图进行刷新。

可是上一篇文章中检查TRACE文件明明看到物化视图的刷新执行了两次,为什么通过触发器的方式发现物化视图仅刷新了一次呢。数据库的测试版本、平台都是相同的,实际上两个测试是在同一个数据库的同一个用户下进行的,除了监测刷新的方法不同之外,唯一的区别就是LOB字段的长度有区别。

记得在第一篇文章的时候使用长度小于4000的字符串测试是,通过SQL_TRACE方式检查,发现物化视图的LOB字段也是只更新了一次。

由于32K正好是VARCHAR2类型和CLOB类型的边界,不会是Oracle处理数据边界的时候出现了重复的情况吧:

SQL> DECLARE
  2     V_STR VARCHAR2(32767) := RPAD('A', 32767, 'A');
  3  BEGIN
  4     INSERT INTO T VALUES (2, 'TEST', V_STR);
  5     COMMIT;
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
32767
32767

PL/SQL procedure successfully completed.

SQL> UPDATE T
  2  SET NAME = 'ABC'
  3  WHERE ID = 2;

1 row updated.

SQL> COMMIT;

Commit complete.

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
32767
32767

PL/SQL procedure successfully completed.

SQL> DECLARE
  2     V_STR VARCHAR2(32767) := RPAD('A', 32766, 'A');
  3  BEGIN
  4     INSERT INTO T VALUES (3, 'TEST', V_STR);
  5     COMMIT;
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
32766

PL/SQL procedure successfully completed.

果然如此,没想到Oracle居然会出现这种低级的错误,不但对于不需要更新的LOB列进行了更新,而且对于32767长度的LOB类型,居然导致物化视图的LOB列刷新了两次。

 

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4227/viewspace-619523/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1964
  • 访问量
    11076238