以前写过一篇文章描述物化视图是否进行字段级的刷新。当时得出的结论是包含LOB字段的物化视图会进行字段级的刷新,但是这个结论是在9.2上得出的,最近测试发现,10g上的结果有所不同。
这篇文章对比9i和11g包含LOB的物化视图的刷新性能。
包含LOB的物化视图快速刷新:http://yangtingkun.itpub.net/post/468/493060
包含LOB的物化视图快速刷新(二):http://yangtingkun.itpub.net/post/468/493206
包含LOB的物化视图快速刷新(三):http://yangtingkun.itpub.net/post/468/493660
物化视图是否根据字段进行刷新(一):http://yangtingkun.itpub.net/post/468/201236
物化视图是否根据字段进行刷新(二):http://yangtingkun.itpub.net/post/468/201607
物化视图是否根据字段进行刷新(三):http://yangtingkun.itpub.net/post/468/203414
有了前面几篇文章中理论的基础,这里做一个简单的测试,分别在9.2和11.2上执行物化视图的刷新。为了公平,不同版本的两个数据库处于同一台服务器上,而且二者的SGA也相差不大。
SQL> set sqlp 'SQL9.2> '
SQL9.2> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production
PL/SQL Release 9.2.0.4.0 - Production
CORE 9.2.0.3.0 Production
TNS for Linux: Version 9.2.0.4.0 - Production
NLSRTL Version 9.2.0.4.0 - Production
SQL9.2> host hostname
bjtest
SQL9.2> show sga
Total System Global Area 5121220856 bytes
Fixed Size 749816 bytes
Variable Size 822083584 bytes
Database Buffers 4294967296 bytes
Redo Buffers 3420160 bytes
上面是9.2的会话,下面的会话连接的是11.2:
SQL> set sqlp 'SQL11.2> '
SQL11.2> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
SQL11.2> host hostname
bjtest
SQL11.2> show sga
Total System Global Area 6814535680 bytes
Fixed Size 2214016 bytes
Variable Size 4093642624 bytes
Database Buffers 2684354560 bytes
Redo Buffers 34324480 bytes
首先对比一下包含大量内容的LOB的物化视图的刷新:
SQL9.2> CREATE TABLE T
2 (
3 ID NUMBER,
4 NAME VARCHAR2(30),
5 CONTENTS CLOB,
6 CONSTRAINT PK_T PRIMARY KEY (ID)
7 );
表已创建。
SQL9.2> 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..1000 LOOP
7 DBMS_LOB.WRITEAPPEND(V_LOB, LENGTH(V_STR), V_STR);
8 END LOOP;
9 COMMIT;
10 END;
11 /
PL/SQL 过程已成功完成。
SQL9.2> CREATE MATERIALIZED VIEW LOG ON T;
实体化视图日志已创建。
SQL9.2> CREATE MATERIALIZED VIEW MV_T REFRESH FAST AS
2 SELECT *
3 FROM T;
实体化视图已创建。
SQL9.2> UPDATE T
2 SET NAME = 'ABC'
3 WHERE ID = 1;
已更新 1 行。
SQL9.2> COMMIT;
提交完成。
SQL9.2> SET TIMING ON
SQL9.2> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 过程已成功完成。
已用时间: 00: 00: 00.40
SQL9.2> SELECT ID, NAME
2 FROM T;
ID NAME
---------- ------------------------------
1 ABC
看看11.2的情况,执行同样的操作:
SQL11.2> CREATE TABLE T
2 (
3 ID NUMBER,
4 NAME VARCHAR2(30),
5 CONTENTS CLOB,
6 CONSTRAINT PK_T PRIMARY KEY (ID)
7 );
表已创建。
SQL11.2> 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..1000 LOOP
7 DBMS_LOB.WRITEAPPEND(V_LOB, LENGTH(V_STR), V_STR);
8 END LOOP;
9 COMMIT;
10 END;
11 /
PL/SQL 过程已成功完成。
SQL11.2> CREATE MATERIALIZED VIEW LOG ON T;
实体化视图日志已创建。
SQL11.2> CREATE MATERIALIZED VIEW MV_T REFRESH FAST AS
2 SELECT *
3 FROM T;
实体化视图已创建。
SQL11.2> UPDATE T
2 SET NAME = 'ABC'
3 WHERE ID = 1;
已更新 1 行。
SQL11.2> COMMIT;
提交完成。
SQL11.2> SET TIMING ON
SQL11.2> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 过程已成功完成。
已用时间: 00: 00: 02.12
SQL11.2> SELECT ID, NAME
2 FROM T;
ID NAME
---------- ------------------------------
1 ABC
由于9i中不需要更新LOB列,因此物化视图的刷新只用了0.4秒,而11.2比9.2高了2个大版本、4个小版本,但是由于需要更新不必要的LOB列,因此花费了2秒多的时间来刷新物化视图。
下面在看看LOB长度为32767的LOB的刷新问题:
SQL9.2> DELETE T;
已删除 1 行。
已用时间: 00: 00: 00.13
SQL9.2> DECLARE
2 V_STR VARCHAR2(32767) := RPAD('A', 32767, 'A');
3 BEGIN
4 FOR I IN 1..1000 LOOP
5 INSERT INTO T VALUES (I, 'TEST', V_STR);
6 END LOOP;
7 COMMIT;
8 END;
9 /
PL/SQL 过程已成功完成。
已用时间: 00: 00: 13.27
SQL9.2> COMMIT;
提交完成。
已用时间: 00: 00: 00.00
SQL9.2> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 过程已成功完成。
已用时间: 00: 00: 17.02
SQL9.2> UPDATE T SET NAME = 'ABC';
已更新1000行。
已用时间: 00: 00: 00.10
SQL9.2> COMMIT;
提交完成。
已用时间: 00: 00: 00.01
SQL9.2> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 过程已成功完成。
已用时间: 00: 00: 00.32
由于没有更新LOB列,物化视图的刷新只用了0.32秒,下面看看11.2的情况:
SQL11.2> DELETE T;
已删除 1 行。
已用时间: 00: 00: 00.24
SQL11.2> DECLARE
2 V_STR VARCHAR2(32767) := RPAD('A', 32767, 'A');
3 BEGIN
4 FOR I IN 1..1000 LOOP
5 INSERT INTO T VALUES (I, 'TEST', V_STR);
6 END LOOP;
7 COMMIT;
8 END;
9 /
PL/SQL 过程已成功完成。
已用时间: 00: 00: 03.18
SQL11.2> COMMIT;
提交完成。
已用时间: 00: 00: 00.00
SQL11.2> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 过程已成功完成。
已用时间: 00: 00: 10.41
SQL11.2> UPDATE T SET NAME = 'ABC';
已更新1000行。
已用时间: 00: 00: 00.09
SQL11.2> COMMIT;
提交完成。
已用时间: 00: 00: 00.00
SQL11.2> EXEC DBMS_MVIEW.REFRESH('MV_T')
PL/SQL 过程已成功完成。
已用时间: 00: 00: 11.48
对于11.2的情况,由于物化视图的刷新没有对LOB列单独处理,且当LOB列的数据长度为32767时,会进行两次更新,导致物化视图的刷新时间将近11.5秒。
对比上面所有的操作,基本上都是11.2的处理能力要比9.2效率高,但是在包含LOB的物化视图刷新上,显然9i中的处理更加合理。
不知道是bug的原因还是Oracle出于其他的考虑,导致10g以后的版本在包含LOB的物化视图的刷新问题上,没有再采用列级的方式,从而导致了物化视图刷新性能的降低。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4227/viewspace-620255/ ,如需转载,请注明出处,否则将追究法律责任。