【问题标题】:Create materialised view without data创建没有数据的物化视图
【发布时间】:2020-07-08 03:57:03
【问题描述】:

我需要创建没有数据的物化视图test,然后我将创建一个脚本来第一次将数据插入到这个物化视图中。在此之后,我将运行物化视图刷新以每晚刷新视图。

由于我不是物化视图方面的专家,任何人都可以在这里帮助我。

目前我有创建物化视图的脚本,它运行了 2 个小时,有 2000 万行。

create materialize view

【问题讨论】:

  • 在 Oracle 文档中,我刚刚遇到过这个......“当物化视图被定义为 BUILD IMMEDIATE 时,会发生完全刷新,除非物化视图 [.. .] 被定义为BUILD DEFERRED。"

标签: oracle plsql


【解决方案1】:

如果我对问题的理解正确,您想将 MV 的创建分解为单独的步骤:

  1. 创建一个空表/物化视图。
  2. 填充它。
  3. 安排夜间刷新过程。

为此,您可以使用on prebuilt table 子句将普通表更改为物化视图。

演示源表:

create table demo_source (id, name) as
select 1, 'Red' from dual union all
select 2, 'Yellow' from dual union all
select 3, 'Orange' from dual union all
select 4, 'Blue' from dual;

将成为我们的 MV 的新表(您也可以使用 create table as select 填充它,或者您可以像任何普通表一样使用显式列名、数据类型、约束、分区等来创建它):

create table demo_mv as
select * from demo_source s
where 1 = 2;

使用单独的insert 步骤填充它:

insert into demo_mv
select * from demo_source;

现在我们把它从一个普通的表格转换成一个 MV:

create materialized view demo_mv on prebuilt table
as
select * from demo_source;

现在DEMO_MV 是一个物化视图。

【讨论】:

  • This.WHERE 1=2 is.a.really.smart.trick!我一直在其他地方使用它,但从没想过在这里使用它。我也同意预建表的必要性,因为我从未遇到过不需要索引的大型旧 mv,并且预建表可确保始终生成(不会被遗忘)。
【解决方案2】:

如果我是你,我会“按原样”创建物化视图(即没有你提到的限制)。

无论如何:最简单的选择是在 WHERE 子句中包含 false 条件,该条件创建没有数据的对象,例如

SQL> create materialized view mv_dept as
  2  select * from dept
  3  where 1 = 2;               --> this

Materialized view created.

SQL> select * from mv_dept;

no rows selected

SQL> desc mv_dept;
 Name                          Null?    Type
 ----------------------------- -------- --------------------
 DEPTNO                        NOT NULL NUMBER(2)
 DNAME                                  VARCHAR2(14)
 LOC                                    VARCHAR2(13)

SQL>

【讨论】:

  • 问题是1=2 条件被“嵌入”到Oracle 对物化视图的定义中。如果你在这个物化视图上运行DBMS_MVIEW.REFRESH,你将永远不会得到任何数据。 OP 想要的是使用正确的定义将实体化视图添加到 Oracle,只是在他/她的脚本稍后刷新它之前不要用数据填充它。
【解决方案3】:

我也有同样的问题。在部署时,我不希望刷新花费太多时间。所以这里我认为是一个更好的解决方案。

drop materialized view test_mv;

create materialized view test_mv 
as select * from all_objects 
where 1 = ( select count(*) from user_tables where table_name = 'TEST_MV' )  ;

select * From test_mv
 => null 

exec DBMS_MVIEW.REFRESH('TEST_MV', method => 'C', atomic_refresh => FALSE, out_of_place => false , PARALLELISM => 4);
 
select * From test_mv
 => result is now of all objects 

【讨论】:

    猜你喜欢
    • 2021-01-15
    • 2017-11-08
    • 2021-05-04
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 2020-04-11
    • 2015-02-11
    • 2019-11-30
    相关资源
    最近更新 更多