利用PCT解決快速重新整理效能問題

space6212發表於2019-04-03

在資料倉儲的一個應用中,有一個這樣的案例:

1. 源表很大,且是根據天做的分割槽表
2. 正常情況下,每天凌晨往源表一次性匯入上一天的資料
3. 正常情況下,資料匯入後不會做任何的修改和刪除操作
4. 有其他的應用需要對這個源表的資料做聚合查詢(group by),其他一個維度是分割槽鍵
[@more@]PCT快速重新整理是Oracle的的一個新特性,可以讓基於分割槽表的物化檢視在不需要物化檢視日誌的情況下,實現快速重新整理。當然這種重新整理的粒度是分割槽級的,不能精確到行級。要啟用PCT快速重新整理,無需特別設定。
原來其他同事建立了物化檢視日誌來實現快速重新整理,實際上,分析一下上面的例子,用物化檢視日誌來重新整理非常不合理,因為每次重新整理都需要重新整理一整個分割槽的資料,重新整理效率不高,且物化檢視日誌對資料匯入的效能影響還是很大的。
其實上面的情形很適用於PCT重新整理,因此可以用PCT快速重新整理來解決以上問題,使得既可以做到快速重新整理,又可以減少mlog帶來的額外開銷。

--首先建立一個分割槽表
SQL> create table test
2 (
3 a date,
4 b char(20),
5 c char(20),
6 d char(20)
7 )
8 partition by range(a)
9 (
10 partition partition_2009 values less than(to_date('2010-01-01','yyyy-mm-dd')),
11 partition partition_2010 values less than(to_date('2011-01-01','yyyy-mm-dd')),
12 partition partition_2011 values less than(to_date('2012-01-01','yyyy-mm-dd'))
13 );

Table created

--建立物化檢視日誌
SQL> create materialized view log on test with rowid;

Materialized view log created

SQL> create materialized view mv_test refresh fast on demand as
2 select a,count(1) cnt from
3 test
4 group by a;

Materialized view created

--寫入大量資料
SQL> insert into test select to_date('2009-01-01','yyyy-mm-dd'),'b','c','d' from dual connect by rownum<=5000000;

已建立5000000行。

已用時間: 00: 04: 11.21

統計資訊
----------------------------------------------------------
5017881 recursive calls
10877553 db block gets
124205 consistent gets
9 physical reads
2978381980 redo size
680 bytes sent via SQL*Net to client
646 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
7 sorts (memory)
0 sorts (disk)
5000000 rows processed

SQL> commit;

用時很長,花了4分多鐘,redo量接近3000M。

--快速重新整理
SQL> exec dbms_mview.refresh('mv_test','f')

PL/SQL 過程已成功完成。

已用時間: 00: 08: 03.40

--花了8分鐘
SQL> drop materialized view log on test;

實體化檢視日誌已刪除。

--在沒有物化檢視日誌的情況下寫入大量資料
SQL> insert into test select to_date('2010-01-01','yyyy-mm-dd'),'b','c','d' from dual connect by rownum<=5000000;

已建立5000000行。

已用時間: 00: 00: 34.23

統計資訊
----------------------------------------------------------
7800 recursive calls
457969 db block gets
103279 consistent gets
25 physical reads
434920672 redo size
682 bytes sent via SQL*Net to client
646 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
35 sorts (memory)
0 sorts (disk)
5000000 rows processed

--只用了34秒鐘就完成了,日誌量也只產生了430M,和剛才比,效率提升七八倍。

--看看是否能快速重新整理
SQL> exec dbms_mview.refresh('mv_test','f')

已用時間: 00: 00: 05.50

SQL> exec dbms_mview.refresh('mv_test','c')

已用時間: 00: 00: 11.75


對比一下快速重新整理和全部重新整理的時間,可以知道,快速重新整理涉及到的資料量肯定比完全重新整理少,間接證明了不用物化檢視日誌也可以實現分割槽級別的快速重新整理。


SQL> update test set a= to_date('2010-01-01','yyyy-mm-dd') where a= to_date('2010-01-01','yyyy-mm-dd') and rownum=1;

SQL> commit;

SQL> exec dbms_mview.refresh('mv_test','f')

已用時間: 00: 00: 05.54

我們只更新了一條資料,但卻需要近6秒完成快速重新整理,說明整個增量重新整理是基於分割槽級別的,而不是行級的增量。


當然,上面的證明方法比較簡單,大家如有興趣,可以用10046跟蹤一下重新整理過程,就可以知道PCT是怎麼實現快速重新整理的了。

最後要說明的是:如果物化檢視包含group by語句,則要實現PCT增量重新整理,一個必須條件是分割槽鍵包含在group by子句中。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/231499/viewspace-1044604/,如需轉載,請註明出處,否則將追究法律責任。

相關文章