启用查询计算的 Oracle 物化视图

问题描述

我正在尝试使用 ENABLE ON QUERY computation 创建以下物化视图,但我找不到问题所在。

我有三个主表,其中包含相应的物化视图日志和所需的列。有人可以帮我吗?

谢谢

create materialized view log on alfaods.OdsReceivable with rowid,sequence ( dueDate,recvChargeTypeId,scheduleId,amount ),primary key including new values for fast refresh;

create materialized view log on alfaods.OdsChargeType with rowid,sequence ( code ),primary key including new values for fast refresh;

create materialized view log on alfaods.OdsScheduleMain with rowid,primary key including new values for fast refresh;

那么MV是

create materialized view alfaods.mv_max_fn_date
TABLESPACE TBDATA
CACHE
LOGGING
NOCOMPRESS
noparaLLEL
BUILD IMMEDIATE
REFRESH FAST ON DEMAND
ENABLE QUERY REWRITE
ENABLE ON QUERY computation
AS 
SELECT max(receivable.dueDate) as finalDate,schedule.id as scheduleId,receivable.recvChargeTypeId as recvChargeTypeId,receivable.scheduleId as receivableSchId,receivable.amount as recamount,chargeType.code as ChargTypecode
                   FROM ALFAODS.OdsReceivable receivable
                        INNER JOIN ALFAODS.OdsChargeType chargeType on receivable.recvChargeTypeId = chargeType.id 
                        INNER JOIN ALFAODS.OdsScheduleMain schedule on receivable.scheduleId = schedule.id 
where 
receivable.amount NOT IN (0.01,0.00)
AND chargeType.code = 2 
group by schedule.id,receivable.recvChargeTypeId,receivable.scheduleId,receivable.amount,chargeType.code 
;

当我尝试创建它时,出现此错误

sql> create materialized view alfaods.mv_max_fn_date
TABLESPACE TBDATA
CACHE
LOGGING
NOCOMPRESS
noparaLLEL
BUILD IMMEDIATE
REFRESH FAST ON DEMAND
ENABLE QUERY REWRITE
ENABLE ON QUERY computation
AS
SELECT max(receivable.dueDate) as finalDate,chargeType.code as ChargTypecode
                   FROM ALFAODS.OdsReceivable receivable
                        INNER JOIN ALFAODS.OdsChargeType chargeType on receivable.recvChargeTypeId = chargeType.id
INNER JOIN ALFAODS.OdsScheduleMain schedule on receivable.scheduleId = schedule.id
where
receivable.amount NOT IN (0.01,0.00)
AND chargeType.code = 2
group by schedule.id,chargeType.code
 25  ;
AND chargeType.code = 2
                      *
ERROR at line 23:
ORA-32361: cannot ENABLE ON QUERY computation for the materialized view


Elapsed: 00:00:00.00
sql>

好像where条件有问题,所以我测试了一下,没有where

sql> create materialized view alfaods.mv_max_fn_date
TABLESPACE TBDATA
CACHE
LOGGING
NOCOMPRESS
noparaLLEL
BUILD IMMEDIATE
REFRESH FAST ON DEMAND
ENABLE QUERY REWRITE
ENABLE ON QUERY computation
AS 
SELECT max(receivable.dueDate) as finalDate,chargeType.code as ChargTypecode
                   FROM ALFAODS.OdsReceivable receivable
                        INNER JOIN ALFAODS.OdsChargeType chargeType on receivable.recvChargeTypeId = chargeType.id 
                        INNER JOIN ALFAODS.OdsScheduleMain schedule on receivable.scheduleId = schedule.id 
--where 
--receivable.amount NOT IN (0.01,0.00)
--AND chargeType.code = 2 
group by schedule.id,chargeType.code 
;

INNER JOIN ALFAODS.OdsScheduleMain schedule on receivable.scheduleId = schedule.id
                                                                       *
ERROR at line 20:
ORA-32361: cannot ENABLE ON QUERY computation for the materialized view

更新

我运行了 DBMS_MVIEW.EXPLAIN_MVIEW

set serveroutput on size unlimited echo on long 99999999 longchunksize 99999999 
declare
    a sys.ExplainMVArrayType;
begin
    dbms_mview.explain_mview('SELECT receivable.recvChargeTypeId as recvChargeTypeId,receivable.scheduleId as scheduleId,chargeType.id as ChargeID,max(receivable.dueDate) as finalDate
                         FROM ALFAODS.OdsReceivable receivable
                        INNER JOIN ALFAODS.OdsChargeType chargeType on receivable.recvChargeTypeId = chargeType.id 
group by receivable.recvChargeTypeId,chargeType.id',a);
    dbms_output.put_line('Explain MV '
        || a(1).mvowner || '.' || a(1).mvname);
    for i in 1..a.count loop
        dbms_output.put_line(
            rpad(a(i).capability_name,30)
            || ' [' || case a(i).possible
                       when 'T' then 'TRUE'
                       when 'F' then 'FALSE'
                       else a(i).possible
                       end || ']'
            || case when a(i).related_num != 0 then
                   ' ' || a(i).related_text
                   || ' (' || a(i).related_num || ')'
               end
            || case when a(i).msgno != 0 then
                   ' ' || a(i).msgtxt
                   || ' (' || a(i).msgno || ')'
               end
        );
    end loop;
end;
/

Explain MV .
PCT                            [FALSE]
REFRESH_COMPLETE               [TRUE]
REFRESH_FAST                   [FALSE]
REWRITE                        [TRUE]
REFRESH_FAST_AFTER_INSERT      [FALSE] join may produce duplicate rows in mv
(2059)
REFRESH_FAST_AFTER_INSERT      [FALSE] MV is not fast refreshable even with view
merging (2154)
REFRESH_FAST_AFTER_ONETAB_DML  [FALSE] FINALDATE (193) mv uses the MIN or MAX
aggregate functions (2086)
REFRESH_FAST_AFTER_ONETAB_DML  [FALSE] see the reason why
REFRESH_FAST_AFTER_INSERT is disabled (2146)
REFRESH_FAST_AFTER_ONETAB_DML  [FALSE] mv uses the MIN or MAX aggregate
functions (2086)
REFRESH_FAST_AFTER_ANY_DML     [FALSE] see the reason why
REFRESH_FAST_AFTER_ONETAB_DML is disabled (2161)
REFRESH_FAST_PCT               [FALSE] PCT FAST REFRESH is not possible if query
contains an inline view (2196)
REWRITE_FULL_TEXT_MATCH        [TRUE]
REWRITE_PARTIAL_TEXT_MATCH     [TRUE]
REWRITE_GENERAL                [FALSE] the reason why the capability is disabled
has escaped analysis (2141)
REWRITE_PCT                    [FALSE] general rewrite is not possible or PCT is
not possible on any of the detail tables (2158)

解决方法

我终于可以制作这样的MV了。我不得不从 MV 中删除 MAX 函数,而我会在查询中使用它,这是我想避免的。无论如何,这里是脚本

SQL> @rebmv.sql
SQL> drop materialized view log on alfaods.OdsScheduleMain ;

Materialized view log dropped.

Elapsed: 00:00:00.05
SQL> drop materialized view log on alfaods.OdsChargeType ;

Materialized view log dropped.

Elapsed: 00:00:00.03
SQL> drop materialized view log on alfaods.OdsReceivable ;

Materialized view log dropped.

Elapsed: 00:00:00.04
SQL> drop materialized view alfaods.mv_max_fn_date ;

Materialized view dropped.

Elapsed: 00:00:00.14
SQL>
SQL> create materialized view log on alfaods.OdsScheduleMain with rowid,sequence ( maturityDate,alfascheduleidentifier,scheduleStatus,terminationDate,totalAssetCostFinanced,capitalOutstanding,activationDate,agreementId,invCusId,dealerid,invCompanyId,agrCompanyId ),primary key including new values for fast refresh;

Materialized view log created.

Elapsed: 00:00:00.06
SQL>
SQL> create materialized view log on alfaods.OdsChargeType with rowid,sequence ( code ),primary key including new values for fast refresh;

Materialized view log created.

Elapsed: 00:00:00.03
SQL>
SQL> create materialized view log on alfaods.OdsReceivable with rowid,sequence ( dueDate,recvChargeTypeId,scheduleId,amount ),primary key including new values for fast refresh;

Materialized view log created.

Elapsed: 00:00:00.02
SQL>
SQL> create materialized view alfaods.mv_max_fn_date
  2  TABLESPACE TBDATA
  3  CACHE
  4  LOGGING
  5  NOCOMPRESS
  6  NOPARALLEL
  7  BUILD IMMEDIATE
  8  REFRESH FAST ON DEMAND
  9  ENABLE QUERY REWRITE
 10  ENABLE ON QUERY COMPUTATION
 11  AS
 12  SELECT count(*) as contador,13         receivable.dueDate as finalDate,14         schedule.id as scheduleId,15         receivable.recvChargeTypeId as recvChargeTypeId,16             receivable.scheduleId as recScheduleId
 17          FROM ALFAODS.OdsReceivable receivable
 18        INNER JOIN ALFAODS.OdsChargeType chargeType on receivable.recvChargeTypeId = chargeType.id
 19            INNER JOIN ALFAODS.OdsScheduleMain schedule on receivable.scheduleId = schedule.id
 20  where
 21  receivable.amount NOT IN (0.01,0.00)
 22  AND chargeType.code = 2
 23  group by receivable.dueDate,schedule.id,receivable.recvChargeTypeId,receivable.scheduleId
 24  ;

Materialized view created.

Elapsed: 00:00:21.94
SQL>
SQL> create index alfaods.idx_mv_max_fn_date on alfaods.mv_max_fn_date ( scheduleId ) nologging nocompress tablespace tbdata ;

Index created.

Elapsed: 00:00:04.13
SQL>
SQL> exec dbms_stats.gather_table_stats('ALFAODS','MV_MAX_FN_DATE',method_opt=> 'FOR ALL COLUMNS SIZE AUTO',cascade => true);

PL/SQL procedure successfully completed.

Elapsed: 00:00:08.36
SQL>
SQL> exec dbms_mview.refresh ('ALFAODS.MV_MAX_FN_DATE','F');

PL/SQL procedure successfully completed.

Elapsed: 00:00:01.46
SQL>