10G物化视图PCT快速刷新不再需要物化视图日志

    Oracle10g增加了物化视图PCT快速刷新的支持,使用PCT快速刷新不再需要物化视图日志。

    在9i中,物化视图的快速刷新必须建立物化视图日志,否则物化视图无法快速刷新:

SQL> CREATE TABLE T
2 (
3 ID NUMBER,
4 NAME VARCHAR2(30),
5 CONSTRAINT PK_T PRIMARY KEY (ID)
6 )
7 PARTITION BY RANGE (ID)
8 (
9 PARTITION P1 VALUES LESS THAN (100),
10 PARTITION P2 VALUES LESS THAN (200),
11 PARTITION P3 VALUES LESS THAN (MAXVALUE)
12 );

表已创建。

SQL> CREATE MATERIALIZED VIEW MV_T REFRESH FAST AS
2 SELECT * FROM T;
SELECT * FROM T
*第 2 行出现错误:
ORA-23413: 表 "TEST"."T" 不带实体化视图日志

SQL> 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

    在10g中,分区表不再需要建立物化视图日志就可以实现物化视图的快速刷新:

SQL> CONN YANGTK/YANGTK@YTK已连接。
SQL> SELECT * FROM V$VERSION;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Prod
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for 32-bit Windows: 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 CONSTRAINT PK_T PRIMARY KEY (ID)
6 )
7 PARTITION BY RANGE (ID)
8 (
9 PARTITION P1 VALUES LESS THAN (100),
10 PARTITION P2 VALUES LESS THAN (200),
11 PARTITION P3 VALUES LESS THAN (MAXVALUE)
12 );

表已创建。

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

实体化视图已创建。

    虽然Oracle支持不建立物化视图日志,但是要注意,不建立物化视图日志的快速刷新采用的是PCT的快速刷新,而不是普通的增量刷新。

SQL> @?/RDBMS/ADMIN/UTLXMV

表已创建。
脚本内容如下:
CREATE TABLE MV_CAPABILITIES_TABLE
  (STATEMENT_ID         VARCHAR(30),  -- Client-supplied unique statement identifier
   MVOWNER              VARCHAR(30),  -- NULL for SELECT based EXPLAIN_MVIEW
   MVNAME               VARCHAR(30),  -- NULL for SELECT based EXPLAIN_MVIEW
   CAPABILITY_NAME      VARCHAR(30),  -- A descriptive name of the particular
                                      -- capability:
                                      -- REWRITE
                                      --   Can do at least full text match
                                      --   rewrite
                                      -- REWRITE_PARTIAL_TEXT_MATCH
                                      --   Can do at leat full and partial
                                      --   text match rewrite
                                      -- REWRITE_GENERAL
                                      --   Can do all forms of rewrite
                                      -- REFRESH
                                      --   Can do at least complete refresh
                                      -- REFRESH_FROM_LOG_AFTER_INSERT
                                      --   Can do fast refresh from an mv log
                                      --   or change capture table at least
                                      --   when update operations are
                                      --   restricted to INSERT
                                      -- REFRESH_FROM_LOG_AFTER_ANY
                                      --   can do fast refresh from an mv log
                                      --   or change capture table after any
                                      --   combination of updates
                                      -- PCT
                                      --   Can do Enhanced Update Tracking on
                                      --   the table named in the RELATED_NAME
                                      --   column.  EUT is needed for fast
                                      --   refresh after partitioned
                                      --   maintenance operations on the table
                                      --   named in the RELATED_NAME column
                                      --   and to do non-stale tolerated
                                      --   rewrite when the mv is partially
                                      --   stale with respect to the table
                                      --   named in the RELATED_NAME column.
                                      --   EUT can also sometimes enable fast
                                      --   refresh of updates to the table
                                      --   named in the RELATED_NAME column
                                      --   when fast refresh from an mv log
                                      --   or change capture table is not
                                      --   possilbe.
   POSSIBLE             CHARACTER(1), -- T = capability is possible
                                      -- F = capability is not possible
   RELATED_TEXT         VARCHAR(2000),-- Owner.table.column, alias name, etc.
                                      -- related to this message.  The
                                      -- specific meaning of this column
                                      -- depends on the MSGNO column.  See
                                      -- the documentation for
                                      -- DBMS_MVIEW.EXPLAIN_MVIEW() for details
   RELATED_NUM          NUMBER,       -- When there is a numeric value
                                      -- associated with a row, it goes here.
                                      -- The specific meaning of this column
                                      -- depends on the MSGNO column.  See
                                      -- the documentation for
                                      -- DBMS_MVIEW.EXPLAIN_MVIEW() for details
   MSGNO                INTEGER,      -- When available, QSM message #
                                      -- explaining why not possible or more
                                      -- details when enabled.
   MSGTXT               VARCHAR(2000),-- Text associated with MSGNO.
   SEQ                  NUMBER);     

SQL> EXEC DBMS_MVIEW.EXPLAIN_MVIEW('SELECT * FROM T')

PL/SQL 过程已成功完成。

SQL> SELECT CAPABILITY_NAME, POSSIBLE, MSGTXT
2 FROM MV_CAPABILITIES_TABLE;

CAPABILITY_NAME P MSGTXT
------------------------------ - ---------------------------------------------
PCT Y
REFRESH_COMPLETE Y
REFRESH_FAST Y
REWRITE Y
PCT_TABLE Y
REFRESH_FAST_AFTER_INSERT N 详细信息表没有实体化视图日志
REFRESH_FAST_AFTER_ONETAB_DML N 查看禁用 REFRESH_FAST_AFTER_INSERT 的原因
REFRESH_FAST_AFTER_ANY_DML N 查看禁用 REFRESH_FAST_AFTER_ONETAB_DML 的原因
REFRESH_FAST_PCT Y
REWRITE_FULL_TEXT_MATCH Y
REWRITE_PARTIAL_TEXT_MATCH Y
REWRITE_GENERAL Y
REWRITE_PCT Y
PCT_TABLE_REWRITE Y

已选择14行。

    从上面的信息不难看出,物化视图支持的是PCT快速刷新,而不是增量刷新,这就意味着进行普通增量修改的刷新将花费大量的时间:

SQL> INSERT INTO T SELECT ROWNUM, OBJECT_NAME FROM DBA_OBJECTS;

已创建50691行。

SQL> COMMIT;

提交完成。

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')

PL/SQL 过程已成功完成。

SQL> SELECT COUNT(*) FROM T;

COUNT(*)
----------
50691

SQL> SELECT COUNT(*) FROM MV_T;

COUNT(*)
----------
50691

下面对比一下删除一条记录对应的刷新时间:

SQL> DELETE T WHERE ID = 1;

已删除 1 行。

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

PL/SQL 过程已成功完成。

已用时间: 00: 00: 00.09

SQL> DELETE T WHERE ID = 10000;

已删除 1 行。

已用时间: 00: 00: 00.03
SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')

PL/SQL 过程已成功完成。

已用时间: 00: 00: 06.01

    从执行时间不难分析出,PCT刷新是针对某个分区进行的刷新,而每次刷新的应该是整个分区。由于ID为1的记录所在分区数据量小,刷新速度就很快,而ID为10000的记录对应的分区数据量大,因此刷新所需时间就长。

    在这种情况下建立物化视图,如果建立了物化视图日志,Oracle在确认可以正常使用物化视图日志后,就会选择利用物化视图日志尽量增量刷新,下面可以对比一下两种刷新对于普通增量刷新的性能:

SQL> SELECT MVIEW_NAME, REFRESH_METHOD, FAST_REFRESHABLE, LAST_REFRESH_TYPE
2 FROM USER_MVIEWS
3 WHERE MVIEW_NAME = 'MV_T';

MVIEW_NAME REFRESH_ FAST_REFRESHABLE LAST_REF
------------------------------ -------- ------------------ --------
MV_T FAST DML FAST_PCT

SQL> CREATE MATERIALIZED VIEW LOG ON T;

实体化视图日志已创建。

SQL> DELETE T WHERE ID = 10001;

已删除 1 行。

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')

PL/SQL 过程已成功完成。

已用时间: 00: 00: 03.64

SQL> SELECT MVIEW_NAME, REFRESH_METHOD, FAST_REFRESHABLE, LAST_REFRESH_TYPE
2 FROM USER_MVIEWS
3 WHERE MVIEW_NAME = 'MV_T';

MVIEW_NAME REFRESH_ FAST_REFRESHABLE LAST_REF
------------------------------ -------- ------------------ --------
MV_T FAST DML FAST_PCT

SQL> DELETE T WHERE ID = 10002;

已删除 1 行。

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')

PL/SQL 过程已成功完成。

已用时间: 00: 00: 00.25
SQL> SELECT MVIEW_NAME, REFRESH_METHOD, FAST_REFRESHABLE, LAST_REFRESH_TYPE
2 FROM USER_MVIEWS
3 WHERE MVIEW_NAME = 'MV_T';

MVIEW_NAME REFRESH_ FAST_REFRESHABLE LAST_REF
------------------------------ -------- ------------------ --------
MV_T FAST DML FAST

    可以看到,虽然PCT刷新使得物化视图日志不再是物化视图快速刷新的必要条件,但是仍然推荐对于分区表建立物化视图日志。因为PCT刷新是针对整个分区而言,而用来进行日常增量代价要比物化视图方式大得多,最好的方法仍然是物化视图日志配合PCT来进行物化视图的快速刷新。

    上面内容推断出物化视图的PCT刷新只针对整个分区进行的。下面通过TRACE的方式来深入研究一下,PCT刷新的工作机制:

SQL> CREATE TABLE T
2 (
3 ID NUMBER,
4 NAME VARCHAR2(30),
5 CONSTRAINT PK_T PRIMARY KEY (ID)
6 )
7 PARTITION BY RANGE (ID)
8 (
9 PARTITION P1 VALUES LESS THAN (100),
10 PARTITION P2 VALUES LESS THAN (200),
11 PARTITION P3 VALUES LESS THAN (MAXVALUE)
12 );

表已创建。

SQL> INSERT INTO T SELECT ROWNUM, OBJECT_NAME FROM DBA_OBJECTS;

已创建50642行。

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

实体化视图已创建。

    下面对T表进行DML和DDL,看看Oracle是如何进行PCT快速刷新的:

SQL> DELETE T PARTITION (P3) WHERE ROWNUM = 1;

已删除 1 行。

SQL> ALTER TABLE T TRUNCATE PARTITION P2;

表被截断。

SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';

会话已更改。

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')

PL/SQL 过程已成功完成。

SQL> ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';

会话已更改。

    检查对应的TRACE文件,可以在TRACE文件中看到下面几条语句:
=====================
PARSING IN CURSOR #14 len=40 dep=0 uid=61 ct=47 lid=61 tim=50228795616 hv=227083342 ad='33703150'
BEGIN DBMS_MVIEW.REFRESH('MV_T'); END;
END OF STMT
PARSE #14:c=46875,e=125264,p=9,cr=158,cu=0,mis=1,r=0,dep=0,og=1,tim=50228795608
BINDS #14:
=====================
.
.
.
=====================
PARSING IN CURSOR #24 len=130 dep=1 uid=61 ct=7 lid=61 tim=50230157165 hv=1048116798 ad='27e7d114'
/* MV_REFRESH (DEL) */ DELETE FROM "YANGTK"."MV_T" WHERE ( ( (200 <= "ID" OR "ID" IS NULL ) OR (100 <= "ID" AND "ID" < 200) ) )
END OF STMT
PARSE #24:c=0,e=23453,p=0,cr=85,cu=0,mis=1,r=0,dep=1,og=1,tim=50230157157
BINDS #24:
WAIT #24: nam='db file scattered read' ela= 10520 file#=8 block#=6357 blocks=4 obj#=56630 tim=50230167855
WAIT #24: nam='db file sequential read' ela= 258 file#=8 block#=6361 blocks=1 obj#=56630 tim=50230209966
WAIT #24: nam='db file scattered read' ela= 3549 file#=8 block#=6362 blocks=7 obj#=56630 tim=50230224906
WAIT #24: nam='db file scattered read' ela= 644 file#=8 block#=6370 blocks=7 obj#=56630 tim=50230303504
WAIT #24: nam='db file sequential read' ela= 268 file#=8 block#=6377 blocks=1 obj#=56630 tim=50230382642
WAIT #24: nam='db file scattered read' ela= 655 file#=8 block#=6378 blocks=7 obj#=56630 tim=50230395005
=====================
.
.
.
=====================
PARSING IN CURSOR #32 len=198 dep=1 uid=61 ct=2 lid=61 tim=50231430378 hv=958674512 ad='27e7c5a4'
/* MV_REFRESH (INS) */ INSERT /*+ BYPASS_RECURSIVE_CHECK */ INTO "YANGTK"."MV_T"SELECT /*+ X_DYN_PRUNE */ "T"."ID" , "T"."NAME" FROM "T" "T" WHERE ( ( (200 <= "T"."ID" OR "T"."ID" IS NULL ) ) )
END OF STMT
PARSE #32:c=15625,e=14398,p=0,cr=79,cu=0,mis=1,r=0,dep=1,og=1,tim=50231430372
BINDS #32:
=====================

    上面的第一部分是用户发出的命令,对MV_T进行快速刷新,而Oracle实际执行的步骤是后面两个部分。

    Oracle进行的DELETE操作,指定了两个条件,其中(100 <= "ID" AND "ID" < 200)对应DDL中TRUNCATE的分区P2,而条件(200 <= "ID" OR "ID" IS NULL )对应的是分区P3,在执行刷新过程中,Oracle首先删除了物化视图中发生了数据变化的分区对应的数据。随后通过INSERT语句插入P3分区对应的数据。

    显然这个操作过程中,Oracle的基表操作单元为分区,也就是说PCT快速刷新的最小单位是一个分区,即使只发生了一条记录的变化,Oracle也会将整个分区删除,然后重新插入新的数据。

    从上面的删除操作可以看到,对于没有发生数据修改的分区P1,Oracle在刷新的过程中并没有进行处理。

    通过对TRACE文件的分析,确认了PCT的刷新是以分区为单位进行的刷新,因此这种方法应该配合物化视图日志使用,而不应该单独使用。

    PCT快速刷新的刷新单位是分区。不过现在仍然存在一个问题,对于物化视图日志方式的快速刷新,Oracle通过内部触发器,在基表进行DML操作的同时在物化视图日志上记录操作信息,快速刷新的时候根据物化视图日志上面的DML信息,配合基表就可以实现刷新了。但是PCT快速刷新不需要物化视图日志,也就是说,没有通过额外的机制来记录基表的变化,那么Oracle是如何知道哪些分区发生了变化,哪些分区是不需要进行刷新的呢?这个疑问看来仍然需要通过TRACE来解决。

PARSING IN CURSOR #16 len=430 dep=1 uid=0 ct=3 lid=0 tim=50229970671 hv=860000844 ad='27e873c0'
SELECT tname, snapid, flag, flag2, status, master_version, tables, lobmaskvec, query_len, mas_roll_seg, mlink, snapshot, auto_fun, uslog, NVL(rscn, 0), refhnt, objflag, auto_fast, sna_type_oid, sna_type_hashcode, sna_type_owner, sna_type_name, mas_type_oid, mas_type_hashcode, mas_type_owner, mas_type_name, syn_count FROM sys.snap$ WHERE sowner = :1 and vname = :2 and instsite = :3
END OF STMT
PARSE #16:c=0,e=705,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=50229970663
BINDS #31:
kkscoacd
Bind#0
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=086d7b9c bln=22 avl=03 flg=05
value=212
Bind#1
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=086d7b78 bln=24 avl=02 flg=05
value=29
=====================
.
.
.
=====================
PARSING IN CURSOR #31 len=210 dep=2 uid=0 ct=3 lid=0 tim=50229975777 hv=864012087 ad='3364435c'
select /*+ rule */ bucket_cnt, row_cnt, cache_cnt, null_cnt, timestamp#, sample_size, minimum, maximum, distcnt, lowval, hival, density, col#, spare1, spare2, avgcln from hist_head$ where obj#=:1 and intcol#=:2
END OF STMT
EXEC #31:c=0,e=129,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=3,tim=50229975772
FETCH #31:c=0,e=47,p=0,cr=3,cu=0,mis=0,r=1,dep=2,og=3,tim=50229975874
STAT #31 id=1 cnt=115 pid=0 pos=1 bj=255 p='TABLE ACCESS BY INDEX ROWID HIST_HEAD$ (cr=353 pr=2 pw=0 time=29119 us)'
STAT #31 id=2 cnt=115 pid=1 pos=1 bj=257 p='INDEX RANGE SCAN I_HH_OBJ#_INTCOL# (cr=238 pr=1 pw=0 time=11936 us)'
BINDS #16:
kkscoacd
Bind#0
oacdty=01 mxl=32(06) mxlc=00 mal=00 scl=00 pre=00
oacflg=10 fl2=0001 frm=01 csi=852 siz=88 ff=0
kxsbbbfp=04d7dbb4 bln=32 avl=06 flg=05
value="YANGTK"
Bind#1
oacdty=01 mxl=32(04) mxlc=00 mal=00 scl=00 pre=00
oacflg=10 fl2=0001 frm=01 csi=852 siz=0 ff=32
kxsbbbfp=04d7dbd4 bln=32 avl=04 flg=01
value="MV_T"
Bind#2
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=00 fl2=0001 frm=00 csi=00 siz=0 ff=64
kxsbbbfp=04d7dbf4 bln=22 avl=01 flg=01
value=0
EXEC #16:c=15625,e=5674,p=0,cr=39,cu=0,mis=1,r=0,dep=1,og=4,tim=50229976479
FETCH #16:c=0,e=65,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=50229976571
STAT #16 id=1 cnt=1 pid=0 pos=1 bj=212 p='TABLE ACCESS BY INDEX ROWID SNAP$ (cr=2 pr=0 pw=0 time=63 us)'
STAT #16 id=2 cnt=1 pid=1 pos=1 bj=217 p='INDEX UNIQUE SCAN I_SNAP1 (cr=1 pr=0 pw=0 time=27 us)'
=====================
PARSING IN CURSOR #16 len=265 dep=1 uid=0 ct=3 lid=0 tim=50229977029 hv=29191747 ad='27e85394'
SELECT masobj#, masflag, mowner, master, lastsuccess, snaptime, sysdate, loadertime, sysdate, NVL(refscn, 0), fcmaskvec, ejmaskvec, sub_handle, change_view FROM sys.snap_reftime$ WHERE sowner = :1 AND vname = :2 AND instsite = :3 ORDER BY tablenum
END OF STMT
PARSE #16:c=0,e=343,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=50229977022
BINDS #23:
kkscoacd
Bind#0
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=086d7b9c bln=22 avl=03 flg=05
value=220
Bind#1
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=086d7b78 bln=24 avl=02 flg=05
value=7
=====================
.
.
.
=====================
PARSING IN CURSOR #20 len=210 dep=2 uid=0 ct=3 lid=0 tim=50229980422 hv=864012087 ad='3364435c'
select /*+ rule */ bucket_cnt, row_cnt, cache_cnt, null_cnt, timestamp#, sample_size, minimum, maximum, distcnt, lowval, hival, density, col#, spare1, spare2, avgcln from hist_head$ where obj#=:1 and intcol#=:2
END OF STMT
EXEC #20:c=0,e=134,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=3,tim=50229980416
FETCH #20:c=0,e=46,p=0,cr=3,cu=0,mis=0,r=1,dep=2,og=3,tim=50229980518
STAT #20 id=1 cnt=124 pid=0 pos=1 bj=255 p='TABLE ACCESS BY INDEX ROWID HIST_HEAD$ (cr=381 pr=2 pw=0 time=29603 us)'
STAT #20 id=2 cnt=124 pid=1 pos=1 bj=257 p='INDEX RANGE SCAN I_HH_OBJ#_INTCOL# (cr=256 pr=1 pw=0 time=12127 us)'
BINDS #16:
kkscoacd
Bind#0
oacdty=01 mxl=32(06) mxlc=00 mal=00 scl=00 pre=00
oacflg=10 fl2=0001 frm=01 csi=852 siz=88 ff=0
kxsbbbfp=04d7dbb4 bln=32 avl=06 flg=05
value="YANGTK"
Bind#1
oacdty=01 mxl=32(04) mxlc=00 mal=00 scl=00 pre=00
oacflg=10 fl2=0001 frm=01 csi=852 siz=0 ff=32
kxsbbbfp=04d7dbd4 bln=32 avl=04 flg=01
value="MV_T"
Bind#2
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=00 fl2=0001 frm=00 csi=00 siz=0 ff=64
kxsbbbfp=04d7dbf4 bln=22 avl=01 flg=01
value=0
EXEC #16:c=0,e=4175,p=0,cr=28,cu=0,mis=1,r=0,dep=1,og=4,tim=50229981265
FETCH #16:c=0,e=62,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=50229981357
=====================

上面的这两个SQL不但获取了物化视图的一些基本信息,还获取了物化视图上次刷新的SCN信息。

=====================
PARSING IN CURSOR #25 len=71 dep=1 uid=0 ct=3 lid=0 tim=50230015976 hv=3754315372 ad='27e81d6c'
select nvl(max(spare1),0) from tabpart$ where bo# = :1 and spare1 <= :2
END OF STMT
PARSE #25:c=0,e=576,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=50230015967
BINDS #25:
kkscoacd
Bind#0
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=00 fl2=0001 frm=00 csi=00 siz=48 ff=0
kxsbbbfp=079962d0 bln=22 avl=04 flg=05
value=56624
Bind#1
oacdty=02 mxl=22(06) mxlc=00 mal=00 scl=00 pre=00
oacflg=10 fl2=0001 frm=01 csi=00 siz=0 ff=24
kxsbbbfp=079962e8 bln=22 avl=06 flg=01
value=6050226572
EXEC #25:c=0,e=655,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=50230016695
FETCH #25:c=0,e=101,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,tim=50230016824
STAT #25 id=1 cnt=1 pid=0 pos=1 bj=0 p='SORT AGGREGATE (cr=2 pr=0 pw=0 time=119 us)'
STAT #25 id=2 cnt=1 pid=1 pos=1 bj=266 p='TABLE ACCESS BY INDEX ROWID TABPART$ (cr=2 pr=0 pw=0 time=79 us)'
STAT #25 id=3 cnt=3 pid=2 pos=1 bj=269 p='INDEX RANGE SCAN I_TABPART_BOPART$ (cr=1 pr=0 pw=0 time=36 us)'
=====================

这个SQL读取分区表的最大SCN信息。

SQL> CONN YANGTK/YANGTK@YTK102已连接。
SQL> alter index pk_t rebuild;

索引已更改。

SQL> INSERT INTO T VALUES (150, 'A');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> DELETE T PARTITION (P3) WHERE ROWNUM = 1;

已删除 1 行。

SQL> COMMIT;

提交完成。

下面切换回SYS用户,检查TABPART$表:

SQL> CONN / AS SYSDBA已连接。
SQL> SELECT SPARE1 from tabpart$ where bo# = 56624 ;

SPARE1
----------

6050256635
6050256782

由于刚才分别对分区P2和分区P3进行了操作,因此TABPART$中可以看到这两个分区的SPARE1列记录了SCN的值,看到这里已经可以推断出,Oracle是根据分区的SCN是否大于上次刷新的SCN来判断这个分区是否需要进行PCT刷新。

=====================
PARSING IN CURSOR #24 len=374 dep=2 uid=0 ct=3 lid=0 tim=50230096308 hv=236422262 ad='27e7e7dc'
select distinct tp1.obj#, tp1.part# from (select tp.obj#, tp.part# from tabpart$ tp where tp.bo# = :dobj# and tp.spare1 > :lscn union select /*+ ordered use_hash(tp) */ tp.obj#, tp.part# from sumdelta$ s1, tabpart$ tp where tp.bo# = :dobj# and tp.dataobj# = s1.partitionobj# and s1.scn> :lscn) tp1 order by tp1.part#
END OF STMT
PARSE #24:c=0,e=1062,p=0,cr=0,cu=0,mis=1,r=0,dep=2,og=4,tim=50230096302
BINDS #25:
kkscoacd
Bind#0
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=086d7b9c bln=22 avl=03 flg=05
value=157
Bind#1
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=086d7b78 bln=24 avl=02 flg=05
value=2
=====================
PARSING IN CURSOR #25 len=210 dep=3 uid=0 ct=3 lid=0 tim=50230097399 hv=864012087 ad='3364435c'
select /*+ rule */ bucket_cnt, row_cnt, cache_cnt, null_cnt, timestamp#, sample_size, minimum, maximum, distcnt, lowval, hival, density, col#, spare1, spare2, avgcln from hist_head$ where obj#=:1 and intcol#=:2
END OF STMT
EXEC #25:c=15625,e=158,p=0,cr=0,cu=0,mis=0,r=0,dep=3,og=3,tim=50230097387
FETCH #25:c=0,e=40,p=0,cr=2,cu=0,mis=0,r=0,dep=3,og=3,tim=50230097497
STAT #25 id=1 cnt=129 pid=0 pos=1 bj=255 p='TABLE ACCESS BY INDEX ROWID HIST_HEAD$ (cr=404 pr=2 pw=0 time=30095 us)'
STAT #25 id=2 cnt=129 pid=1 pos=1 bj=257 p='INDEX RANGE SCAN I_HH_OBJ#_INTCOL# (cr=274 pr=1 pw=0 time=12353 us)'
BINDS #24:
kkscoacd
Bind#0
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=00 fl2=0001 frm=00 csi=00 siz=48 ff=0
kxsbbbfp=04d7a174 bln=22 avl=04 flg=05
value=56624
Bind#1
oacdty=02 mxl=22(06) mxlc=00 mal=00 scl=00 pre=00
oacflg=10 fl2=0001 frm=00 csi=00 siz=0 ff=24
kxsbbbfp=04d7a18c bln=22 avl=06 flg=01
value=6050226324
Bind#2
No oacdef for this bind.
Bind#3
No oacdef for this bind.
EXEC #24:c=15625,e=2039,p=0,cr=2,cu=0,mis=1,r=0,dep=2,og=4,tim=50230098433
FETCH #24:c=0,e=434,p=0,cr=5,cu=0,mis=0,r=1,dep=2,og=4,tim=50230098887
FETCH #24:c=0,e=7,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=4,tim=50230098944
STAT #24 id=1 cnt=1 pid=0 pos=1 bj=0 p='SORT UNIQUE (cr=5 pr=0 pw=0 time=498 us)'
STAT #24 id=2 cnt=1 pid=1 pos=1 bj=0 p='VIEW (cr=5 pr=0 pw=0 time=457 us)'
STAT #24 id=3 cnt=1 pid=2 pos=1 bj=0 p='SORT UNIQUE (cr=5 pr=0 pw=0 time=431 us)'
STAT #24 id=4 cnt=1 pid=3 pos=1 bj=0 p='UNION-ALL (cr=5 pr=0 pw=0 time=380 us)'
STAT #24 id=5 cnt=1 pid=4 pos=1 bj=266 p='TABLE ACCESS BY INDEX ROWID TABPART$ (cr=2 pr=0 pw=0 time=74 us)'
STAT #24 id=6 cnt=3 pid=5 pos=1 bj=269 p='INDEX RANGE SCAN I_TABPART_BOPART$ (cr=1 pr=0 pw=0 time=36 us)'
STAT #24 id=7 cnt=0 pid=4 pos=2 bj=0 p='HASH JOIN (cr=3 pr=0 pw=0 time=213 us)'
STAT #24 id=8 cnt=0 pid=7 pos=1 bj=157 p='TABLE ACCESS FULL SUMDELTA$ (cr=3 pr=0 pw=0 time=48 us)'
STAT #24 id=9 cnt=0 pid=7 pos=2 bj=266 p='TABLE ACCESS BY INDEX ROWID TABPART$ (cr=0 pr=0 pw=0 time=0 us)'
STAT #24 id=10 cnt=0 pid=9 pos=1 bj=269 p='INDEX RANGE SCAN I_TABPART_BOPART$ (cr=0 pr=0 pw=0 time=0 us)'
=====================

上面的SQL确定需要进行PCT刷新的分区。

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

转载于:http://blog.itpub.net/14270146/viewspace-677009/

你可能感兴趣的:(10G物化视图PCT快速刷新不再需要物化视图日志)