【问题标题】:Materialized View by Joining View and Tables通过连接视图和表实现物化视图
【发布时间】:2020-08-08 01:56:52
【问题描述】:

我们可以通过加入已经存在的视图(普通)来创建物化视图吗?我的要求是在表(A,B)和视图(c)上创建一个 MVIEW。可能吗?如果是,我们是否看到任何性能问题或刷新问题。 这需要在 Oracle DB 上完成。

CREATE MATERIALIZED VIEW EMP_MVIEW refresh force ON COMMIT
select 
EMP.ID, EMP.NAME, DV.*
EMP_TABLE EMP
LEFT OUTER JOIN DETAILS_VIEW dv ON DV.EMP_ID=EMP.EMP_ID

【问题讨论】:

  • 可以在物化视图中引用常规视图。
  • 谢谢。那么常规视图中的所有表也应该有用于增量刷新的 mview 日志?。
  • 如果您需要增量刷新(即快速刷新),您无法添加普通视图并创建它。对于快速刷新,存在限制。见dbarepublic.com/2016/07/…。如果您需要进一步的帮助,请在表格和视图的结构中发布您的要求的详细信息
  • @Sujitmohanty30 - 我们在视图中加入的所有表上都有 mlog。意思是,视图是通过连接 A、B、C 创建的,所有连接列都是主键,我们有 A、B、C 的 mlogs .. 仍然不适用于增量刷新
  • 能否分享一下物化视图的定义?

标签: sql oracle plsql


【解决方案1】:

首先,不幸的是,Oracle 物化视图不允许使用 ANSI 连接语法,请使用旧的 Oracle 连接语法。 It is a bug in Oracle i believe so

我将用我的答案展示的任何内容都只是关于使用 FAST REFRESH 选项实现的物化

回到您最初的问题,我们是否可以在物化视图中使用具有增量刷新功能的普通视图:

答案是

话虽如此,如果我们尝试将导致错误并且无法创建它,如下所示,

表结构:(仅用于演示示例,不用于实际的规范化表

CREATE TABLE emp(emp_id NUMBER primary key
                ,empname VARCHAR2(1000));
CREATE TABLE address_details(address_id NUMBER primary key
                            ,address_text VARCHAR2(1000)
                            ,emp_id NUMBER);
CREATE TABLE salary_details(sal_id NUMBER primary key
                           ,salary NUMBER
                           ,emp_id NUMBER);

物化视图日志:

--drop statements
DROP MATERIALIZED VIEW LOG ON emp;
DROP MATERIALIZED VIEW LOG ON address_details;
DROP MATERIALIZED VIEW LOG ON salary_details;

--create statements

--default
CREATE MATERIALIZED VIEW LOG ON emp;
CREATE MATERIALIZED VIEW LOG ON address_details;
CREATE MATERIALIZED VIEW LOG ON salary_details;

--with primary key (same as default above but I would stick to mention it explicitly for understanding and versioning (svn or git) purpose
CREATE MATERIALIZED VIEW LOG ON emp WITH PRIMARY KEY;
CREATE MATERIALIZED VIEW LOG ON address_details WITH PRIMARY KEY;
CREATE MATERIALIZED VIEW LOG ON salary_details WITH PRIMARY KEY;

--with primary key and rowid
CREATE MATERIALIZED VIEW log ON emp WITH PRIMARY KEY, ROWID;
CREATE MATERIALIZED VIEW log ON address_details WITH PRIMARY KEY, ROWID;
CREATE MATERIALIZED VIEW log ON salary_details WITH PRIMARY KEY, ROWID;

1.首先尝试根据需要创建具有普通视图的 MV:

CREATE OR REPLACE VIEW DETAILS_VIEW AS
SELECT sal_id
      ,salary
      ,address_id
      ,address_text
      ,sl.emp_id
      --,sl.rowid sl_rowid
      --,ad.rowid ad_rowid
FROM   salary_details sl
      ,address_details ad
WHERE  sl.emp_id = ad.emp_id;

DROP MATERIALIZED VIEW emp_mview;

CREATE MATERIALIZED VIEW EMP_MVIEW 
REFRESH FORCE ON COMMIT 
AS
SELECT emp.emp_id
      ,emp.empname
      ,dv.sal_id
      ,dv.salary
      ,dv.address_id
      ,dv.address_text
      --,emp.rowid emp_rowid
      --,dv.sl_rowid
      --,dv.ad_rowid
FROM   emp           emp
      ,details_view  dv
WHERE  emp.emp_id = dv.emp_id(+);

结果:

ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view

相信我,我已经尝试过使用主键和 rowid 创建日志并将 rowid 添加到 select 子句的所有方案,但没有任何效果

前进:

2.第二次尝试通过将所有单个基表放在 from 子句中来使用来自 oracle 的标准连接创建 MV:

我已经创建了带有选项主键的物化视图日志,正如我在上面的物化视图日志部分中提到的那样。

CREATE MATERIALIZED VIEW EMP_MVIEW 
REFRESH FORCE ON COMMIT 
AS
SELECT emp.emp_id
      ,emp.empname
      ,sl.sal_id
      ,sl.salary
      ,ad.address_id
      ,ad.address_text
FROM   emp             emp
      ,salary_details  sl
      ,address_details ad
WHERE  emp.emp_id = sl.emp_id(+)
AND    emp.emp_id = ad.emp_id(+);

宾果游戏:Materialized view created , 但是,等等……这是否意味着我现在可以做一个 FAST REFRESH ?让我们检查一下:

我们可以使用DBMS_MVIEW.EXPLAIN_MVIEW 分析物化视图功能,它将功能详细信息插入到名为MV_CAPABILITIES_TABLE 的表中(可用于@ $ORACLE_HOME/rdbms/admin/utlxmv.sql)。如果我们没有来自 DBA 的脚本和授权,您需要获得它。不过我还是会给出下面的脚本

如何分析 MV 的能力:

    --table structure
    CREATE TABLE mv_capabilities_table (
        statement_id      VARCHAR2(30),
        mvowner           VARCHAR2(30),
        mvname            VARCHAR2(30),
        capability_name   VARCHAR2(30),
        possible          CHAR(1),
        related_text      VARCHAR2(2000),
        related_num       NUMBER,
        msgno             INTEGER,
        msgtxt            VARCHAR2(2000),
        seq               NUMBER
    );
    
    --delete always before analyzing for a view to have only rows for a specific and not to have where clause to filter :)
    DELETE FROM mv_capabilities_table;
    
    --run this script which will analyze and insert into mv_capabilities_table
    BEGIN
       dbms_mview.explain_mview('EMP_MVIEW');
    END;
    /

/***ANALYSIS RESULT:***/

    --I am intersted only with data related to FAST REFRESH category
    SELECT capability_name
         ,possible
         ,substr(msgtxt
                ,1
                ,60) AS msgtxt
    FROM   mv_capabilities_table
    WHERE  capability_name LIKE '%FAST%';
    
    /**
    CAPABILITY_NAME                    POSSIBLE    MSGTXT
    REFRESH_FAST                            N 
    REFRESH_FAST_AFTER_INSERT               N      the SELECT list does not have the rowids of all the detail t
    REFRESH_FAST_AFTER_INSERT               N      mv log must have ROWID
    REFRESH_FAST_AFTER_INSERT               N      mv log must have ROWID
    REFRESH_FAST_AFTER_INSERT               N      mv log must have ROWID
    REFRESH_FAST_AFTER_ONETAB_DML           N      see the reason why REFRESH_FAST_AFTER_INSERT is disabled
    REFRESH_FAST_AFTER_ANY_DML              N      see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled
    REFRESH_FAST_PCT                        N      PCT FAST REFRESH is not possible if query contains LEFT OUTE
    **/

如果您查看带有文本**mv log must have ROWID**上面的分析结果告诉我们物化视图日志缺少ROWID 选项,因此FAST REFRESH 是不可能的。

注意:mv_capabilities_table 中的其他列也会告诉你我没有包含的确切表格,你可以自己检查和测试看看。

前进..

3.第三次尝试使用来自 oracle 的标准连接和包含选项 ROWID 的 MV 日志创建 MV:

步骤:(不再提供脚本,只提供模拟步骤

  • 我将删除并使用选项 ROWID 重新创建 MV 日志,如上面 物化视图日志部分所述。
  • 然后我将删除并重新创建我在第二次尝试中使用的相同的 MV 定义,最终将创建
  • 接下来我将尝试重复如何分析 MV 的能力部分中所述的步骤来分析 MV

我在分析报告中得到了什么:

/**
CAPABILITY_NAME                         POSSIBLE  MSGTXT
REFRESH_FAST                            N 
REFRESH_FAST_AFTER_INSERT               N         the SELECT list does not have the rowids of all the detail t
REFRESH_FAST_AFTER_ONETAB_DML           N         see the reason why REFRESH_FAST_AFTER_INSERT is disabled
REFRESH_FAST_AFTER_ANY_DML              N         see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled
REFRESH_FAST_PCT                        N         PCT FAST REFRESH is not possible if query contains LEFT OUTE
**/

Ufffff:我真的很累,MV 还没有FAST REFRESH 的能力,原因告诉我们"the SELECT list does not have the rowids of all the detail tables"

含义:FAST REFRESH 的下一个条件是Rowids of all the tables in the FROM list must appear in the SELECT list of the query

所以,

4.第四次也是最后一次尝试使用来自 oracle 的标准连接和包含选项 ROWID 的 MV 日志创建 MV,并且详细信息表 rowid 现在包含在 select 子句中:

步骤:

  • 与第 3 次尝试一样,第一次刷新所需的 MV 日志已就位,我将删除并再次重新创建 MV,但这次添加了详细表的 rowid。

MV最终脚本:

CREATE MATERIALIZED VIEW EMP_MVIEW 
REFRESH FORCE ON COMMIT 
AS
SELECT emp.emp_id
      ,emp.empname
      ,sl.sal_id
      ,sl.salary
      ,ad.address_id
      ,ad.address_text
      ,emp.rowid emp_rowid
      ,sl.rowid sl_rowid
      ,ad.rowid ad_rowid
FROM   emp             emp
      ,salary_details  sl
      ,address_details ad
WHERE  emp.emp_id = sl.emp_id(+)
AND    emp.emp_id = ad.emp_id(+);

现在,随着 MV 的创建,让我们再分析一下如何分析 MV 的能力部分中描述的 MV 的能力。 (手指交叉)

结果:

SELECT capability_name
      ,possible
      ,substr(msgtxt,1,60) AS msgtxt
FROM   mv_capabilities_table
WHERE  capability_name LIKE '%FAST%';

/**
CAPABILITY_NAME                         POSSIBLE  MSGTXT
REFRESH_FAST                            Y 
REFRESH_FAST_AFTER_INSERT               Y 
REFRESH_FAST_AFTER_ONETAB_DML           Y 
REFRESH_FAST_AFTER_ANY_DML              Y 
REFRESH_FAST_PCT                        N         PCT FAST REFRESH is not possible if query contains LEFT OUTE
**/

终于REFRESH_FAST 功能成为可能,正如我们所看到的POSSIBLE -> Y

对不起,回答太长了,但我想我应该把我过去在 MV 中学到的东西写出来,这可能对分享有用。

我发现一些对于 Oracle 物化视图总是有用的链接:

干杯!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-06
    • 2011-02-01
    • 2019-10-07
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 2016-02-06
    相关资源
    最近更新 更多