【问题标题】:Oracle - How to create a materialized view with FAST REFRESH and JOINSOracle - 如何使用 FAST REFRESH 和 JOINS 创建物化视图
【发布时间】:2011-11-22 05:33:30
【问题描述】:

所以我很确定 Oracle 支持这一点,所以我不知道我做错了什么。此代码有效:

CREATE MATERIALIZED VIEW MV_Test
  NOLOGGING
  CACHE
  BUILD IMMEDIATE 
  REFRESH FAST ON COMMIT 
  AS
    SELECT V.* FROM TPM_PROJECTVERSION V;

如果我添加一个 JOIN,它会中断:

CREATE MATERIALIZED VIEW MV_Test
  NOLOGGING
  CACHE
  BUILD IMMEDIATE 
  REFRESH FAST ON COMMIT 
  AS
    SELECT V.*, P.* FROM TPM_PROJECTVERSION V
    INNER JOIN TPM_PROJECT P ON P.PROJECTID = V.PROJECTID

现在我得到了错误:

ORA-12054: 无法为实体化视图设置 ON COMMIT 刷新属性

我已经在 TPM_PROJECT 和 TPM_PROJECTVERSION 上创建了物化视图日志。 TPM_PROJECT 的主键为 PROJECTID,TPM_PROJECTVERSION 的复合主键为 (PROJECTID,VERSIONID)。这有什么诀窍?我一直在挖掘 Oracle 手册,但无济于事。谢谢!

【问题讨论】:

  • 你试过DBMS_MVIEW.EXPLAIN_MVIEW吗?它应该向您显示视图的可用选项?
  • 我要做的第一件事是在 select 子句中丢失 *。不确定视图将如何处理重复的列名
  • 是的,我一直在试图弄清楚如何运行 DBMS_MVIEW.EXPLAIN_MVIEW 但还没有让它工作 - 抱歉,我对 Oracle 很陌生。

标签: sql database oracle oracle11g


【解决方案1】:

首先,从Oracle Database Data Warehousing Guide

对仅使用连接的物化视图进行快速刷新的限制

...

  • FROM 列表中所有表的行 ID 必须出现在 SELECT 中 查询列表。

这意味着您的语句需要如下所示:

CREATE MATERIALIZED VIEW MV_Test
  NOLOGGING
  CACHE
  BUILD IMMEDIATE 
  REFRESH FAST ON COMMIT 
  AS
    SELECT V.*, P.*, V.ROWID as V_ROWID, P.ROWID as P_ROWID 
    FROM TPM_PROJECTVERSION V,
         TPM_PROJECT P 
    WHERE P.PROJECTID = V.PROJECTID

另一个需要注意的关键方面是您的物化视图日志必须创建为with rowid

下面是一个功能测试场景:

CREATE TABLE foo(foo NUMBER, CONSTRAINT foo_pk PRIMARY KEY(foo));

CREATE MATERIALIZED VIEW LOG ON foo WITH ROWID;

CREATE TABLE bar(foo NUMBER, bar NUMBER, CONSTRAINT bar_pk PRIMARY KEY(foo, bar));

CREATE MATERIALIZED VIEW LOG ON bar WITH ROWID;

CREATE MATERIALIZED VIEW foo_bar
  NOLOGGING
  CACHE
  BUILD IMMEDIATE
  REFRESH FAST ON COMMIT  AS SELECT foo.foo, 
                                    bar.bar, 
                                    foo.ROWID AS foo_rowid, 
                                    bar.ROWID AS bar_rowid 
                               FROM foo, bar
                              WHERE foo.foo = bar.foo;

【讨论】:

  • Uggghhhh 天哪,谢谢!终于奏效了。我实际上并没有真正理解 Oracle 中的物化视图。它们仅限于对任何人都没有真正用处的程度。我想知道 MS SQL 中的索引视图是否更好。
  • MS SQL 中的索引视图是不同的——它们总是会立即更新,但有一些非常严重的限制,比如没有子查询、没有外连接、没有嵌套索引视图、没有非确定性功能等见docs.microsoft.com/en-us/sql/relational-databases/views/…
【解决方案2】:

你试过没有 ANSI 连接吗?

CREATE MATERIALIZED VIEW MV_Test
  NOLOGGING
  CACHE
  BUILD IMMEDIATE 
  REFRESH FAST ON COMMIT 
  AS
SELECT V.*, P.* FROM TPM_PROJECTVERSION V,TPM_PROJECT P 
WHERE  P.PROJECTID = V.PROJECTID

【讨论】:

  • 嗯,这似乎神奇地工作得更好。但是,现在我收到有关 REFRESH FAST 的错误。如果我将其更改为 REFRESH COMPLETE,它会创建视图。如果每次更新任何基础表时都必须手动运行整个查询,这可能会导致一些非常慢的更新。我虽然允许快速刷新,只要每个表都有物化视图日志。
  • 事实上,前段时间我在甲骨文为此创建了一个案例。 Oracle 认为这只是“缺乏文档”而不是错误!因此,仍然需要旧的 Oracle 连接语法。
【解决方案3】:

如果您没有为查询所引用的主表创建具体化视图日志,您将在 REFRESH_FAST 上收到错误。如果有人不熟悉物化视图或第一次使用它,更好的方法是使用 oracle sqldeveloper 并以图形方式输入选项,并且错误也提供了更好的感觉。

【讨论】:

    【解决方案4】:

    FAST REFRESH 的主要检查包括以下内容:

    1) An Oracle materialized view log must be present for each base table.
    2) The RowIDs of all the base tables must appear in the SELECT list of the MVIEW query definition.
    3) If there are outer joins, unique constraints must be placed on the join columns of the inner table.
    

    第 3 条很容易错过,值得在这里强调

    【讨论】:

      猜你喜欢
      • 2021-01-13
      • 1970-01-01
      • 2014-04-25
      • 2018-07-11
      • 2021-11-22
      • 2021-05-24
      • 1970-01-01
      • 2018-09-13
      相关资源
      最近更新 更多