物化视图:涉及分区运算符的聚合查询

Materialised View : Aggregate query involving partitionn operator

运行 插入墙中,尝试在插入 Tablea

后插入满足特定条件的行 Tableb
drop materialized view mv ;
drop materialized view log on tablea ;

create materialized view log on tablea
with rowid, sequence ( tino, price )
including new values;

create materialized view mv
refresh fast on commit
enable query rewrite
as
SELECT  tino,sum(price)
FROM tablea PARTITION(PART_201609)
group by tino;

以上将 return ORA-12054: 无法设置 ON COMMIT 刷新属性。 这是一个限制吗?聚合查询中没有分区运算符? Table 太大了,我希望我的视图只有特定于某个 period/month 的数据 当我如下所示删除 PARTITION(PART_201609) 和 运行 时,我能够成功创建视图:

create materialized view mv
refresh fast on commit
enable query rewrite
as
SELECT  tino,sum(price)
FROM tablea
group by tino;

-- 编辑 -- 包括 tablea 的 DDL

-- 创建table

create table TABLEA
(
tino  NUMBER not null,
price VARCHAR2(200),
dated DATE
)
partition by range (DATED)
(
partition PART_201608 values less than (TO_DATE(' 2016-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
partition PART_201609 values less than (TO_DATE(' 2016-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
partition PART_201610 values less than (TO_DATE(' 2016-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')));

您可以使用 the dbms_mview.explain_mview procedure 查看为什么您建议的查询不能用于提交时快速刷新 MV:

begin
  dbms_mview.explain_mview(q'[SELECT  tino,sum(price)
FROM tablea PARTITION(PART_201609)
group by tino]');
end;
/

select capability_name, possible, msgno, msgtxt from mv_capabilities_table;

CAPABILITY_NAME                P      MSGNO MSGTXT                                                                                   
------------------------------ - ---------- ------------------------------------------------------------------------------------------
PCT                            N                                                                                                      
REFRESH_COMPLETE               Y                                                                                                      
REFRESH_FAST                   N                                                                                                      
REWRITE                        Y                                                                                                      
PCT_TABLE                      N       2067 no partition key or PMARKER or join dependent expression in select list                   
REFRESH_FAST_AFTER_INSERT      N       2169 the materialized view contains partition extended table name                              
REFRESH_FAST_AFTER_ONETAB_DML  N       2143 SUM(expr) without COUNT(expr)                                                             
REFRESH_FAST_AFTER_ONETAB_DML  N       2146 see the reason why REFRESH_FAST_AFTER_INSERT is disabled                                  
REFRESH_FAST_AFTER_ANY_DML     N       2161 see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled                              
REFRESH_FAST_PCT               N       2157 PCT is not possible on any of the detail tables in the materialized view                  
REWRITE_FULL_TEXT_MATCH        Y                                                                                                      
REWRITE_PARTIAL_TEXT_MATCH     Y                                                                                                      
REWRITE_GENERAL                N       2169 the materialized view contains partition extended table name                              
REWRITE_PCT                    N       2158 general rewrite is not possible or PCT is not possible on any of the detail tables        
PCT_TABLE_REWRITE              N       2185 no partition key or PMARKER in select list                                                

据我所知,没有任何办法解决 2169 错误:

02169, 00000, "the materialized view contains partition extended table name"
// *Cause: Fast refresh of materialized aggregate views and/or materialized
// join views are not supported if they were defined using partition
// extended table names.
// *Action: Create the fast refreshable materialized view without using
// partition extended table names or create the materialized view as
// a complete refresh materialized view.

无论如何,按名称指定分区有点不寻常;您可以通过指定日期范围来实现相同的目的,Oracle 无论如何都会将查询限制在相关分区。您从以下位置获得相同的执行计划:

explain plan for
select tino, sum(price)
from tablea partition(part_201609)
group by tino;

explain plan for
select tino, sum(price)
from tablea
where dated >= date '2016-09-01'
and dated < date '2016-10-01'
group by tino;

--------------------------------------------------------------------------------------------------                                                                                                                                                                                                          
| Id  | Operation               | Name   | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |                                                                                                                                                                                                          
--------------------------------------------------------------------------------------------------                                                                                                                                                                                                          
|   0 | SELECT STATEMENT        |        |     1 |   115 |    15   (7)| 00:00:01 |       |       |                                                                                                                                                                                                          
|   1 |  HASH GROUP BY          |        |     1 |   115 |    15   (7)| 00:00:01 |       |       |                                                                                                                                                                                                          
|   2 |   PARTITION RANGE SINGLE|        |     1 |   115 |    14   (0)| 00:00:01 |     2 |     2 |                                                                                                                                                                                                          
|   3 |    TABLE ACCESS FULL    | TABLEA |     1 |   115 |    14   (0)| 00:00:01 |     2 |     2 |                                                                                                                                                                                                          
--------------------------------------------------------------------------------------------------                                                                                                                                                                                                          

您会看到比我从虚拟 table 中获得的行数更多的行数,但请注意 PSTART 和 PSTOP 列。

尽管将其用于您的 MV 仍然不够:

begin
  dbms_mview.explain_mview(q'[select tino, sum(price)
from tablea
where dated >= date '2016-09-01'
and dated < date '2016-10-01'
group by tino]');
end;
/

select capability_name, possible, msgno, msgtxt from mv_capabilities_table;

CAPABILITY_NAME                P      MSGNO MSGTXT                                                                                   
------------------------------ - ---------- ------------------------------------------------------------------------------------------
PCT                            N                                                                                                      
REFRESH_COMPLETE               Y                                                                                                      
REFRESH_FAST                   N                                                                                                      
REWRITE                        Y                                                                                                      
PCT_TABLE                      N       2067 no partition key or PMARKER or join dependent expression in select list                   
REFRESH_FAST_AFTER_INSERT      N       2081 mv log does not have all necessary columns                                                
REFRESH_FAST_AFTER_ONETAB_DML  N       2143 SUM(expr) without COUNT(expr)                                                             
REFRESH_FAST_AFTER_ONETAB_DML  N       2146 see the reason why REFRESH_FAST_AFTER_INSERT is disabled                                  
REFRESH_FAST_AFTER_ONETAB_DML  N       2142 COUNT(*) is not present in the select list                                                
REFRESH_FAST_AFTER_ONETAB_DML  N       2143 SUM(expr) without COUNT(expr)                                                             
REFRESH_FAST_AFTER_ANY_DML     N       2161 see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled                              
REFRESH_FAST_PCT               N       2157 PCT is not possible on any of the detail tables in the materialized view                  
REWRITE_FULL_TEXT_MATCH        Y                                                                                                      
REWRITE_PARTIAL_TEXT_MATCH     Y                                                                                                      
REWRITE_GENERAL                Y                                                                                                      
REWRITE_PCT                    N       2158 general rewrite is not possible or PCT is not possible on any of the detail tables        
PCT_TABLE_REWRITE              N       2185 no partition key or PMARKER in select list                                                

您需要解决 2067 错误:

02067, 00000, "no partition key or PMARKER or join dependent expression in select list"
// *Cause: The capability in question is not supported when the materialized
// view unless the select list (and group by list if a GROUP BY
// clause is present) includes the partition key or
// PMARKER function reference to the table in question or an expression
// join dependent on the partitioning column of the table in question.
// *Action: Add the partition key or a PMARKER function reference or a join dependent
// expression to the select list (and the GROUP BY clause, if present).

... 与 partition change tracking. You can add a partition marker 有关 select 列表和分组依据,它再次获得相同的执行计划 (PSTART/PSTOP),但现在允许快速-刷新:

explain plan for
select dbms_mview.pmarker(rowid), tino, sum(price)
from tablea
where dated >= date '2016-09-01'
and dated < date '2016-10-01'
group by dbms_mview.pmarker(rowid), tino;

select * from table(dbms_xplan.display);

begin
  dbms_mview.explain_mview(q'[select dbms_mview.pmarker(rowid), tino, sum(price)
from tablea
where dated >= date '2016-09-01'
and dated < date '2016-10-01'
group by dbms_mview.pmarker(rowid), tino]');
end;
/

CAPABILITY_NAME                P      MSGNO MSGTXT                                                                                   
------------------------------ - ---------- ------------------------------------------------------------------------------------------
PCT                            Y                                                                                                      
REFRESH_COMPLETE               Y                                                                                                      
REFRESH_FAST                   Y                                                                                                      
REWRITE                        Y                                                                                                      
PCT_TABLE                      Y                                                                                                      
REFRESH_FAST_AFTER_INSERT      N       2081 mv log does not have all necessary columns                                                
REFRESH_FAST_AFTER_ONETAB_DML  N       2143 SUM(expr) without COUNT(expr)                                                             
REFRESH_FAST_AFTER_ONETAB_DML  N       2146 see the reason why REFRESH_FAST_AFTER_INSERT is disabled                                  
REFRESH_FAST_AFTER_ONETAB_DML  N       2142 COUNT(*) is not present in the select list                                                
REFRESH_FAST_AFTER_ONETAB_DML  N       2143 SUM(expr) without COUNT(expr)                                                             
REFRESH_FAST_AFTER_ANY_DML     N       2161 see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled                              
REFRESH_FAST_PCT               Y                                                                                                      
REWRITE_FULL_TEXT_MATCH        Y                                                                                                      
REWRITE_PARTIAL_TEXT_MATCH     Y                                                                                                      
REWRITE_GENERAL                Y                                                                                                      
REWRITE_PCT                    Y                                                                                                      
PCT_TABLE_REWRITE              Y                                                                                                      

而且您确实可以使用该查询来创建您的 MV:

create materialized view mv
refresh fast on commit
enable query rewrite
as
select dbms_mview.pmarker(rowid), tino, sum(price)
from tablea
where dated >= date '2016-09-01'
and dated < date '2016-10-01'
group by dbms_mview.pmarker(rowid), tino;

Materialized view MV created.

如果您想启用 MV 中的所有功能,您可以将 dated 列添加到您的 MV 日志中:

create materialized view log on tablea
with rowid, sequence ( dated, tino, price )
including new values;

并在您的 MV 查询中包含缺失的聚合:

select dbms_mview.pmarker(rowid), tino, sum(price), count(price), count(*)
from tablea a
where dated >= date '2016-09-01'
and dated < date '2016-10-01'
group by dbms_mview.pmarker(rowid), tino

不相关,但还要注意,如果有益的话,您也可以对 MV 视图日志进行分区:

create materialized view log on tablea
partition by range (dated)
(
  partition PART_201608 values less than (TO_DATE(' 2016-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  partition PART_201609 values less than (TO_DATE(' 2016-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
  partition PART_201610 values less than (TO_DATE(' 2016-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
)
with rowid, sequence ( dated, tino, price )
including new values;