Oracle 如何使用连接和聚合在物化视图上快速刷新?

Oracle 如何使用连接和聚合在物化视图上快速刷新?,oracle,materialized-views,Oracle,Materialized Views,假设我有两个表job和batch: CREATE TABLE batch ( batch_id NUMBER(20) PRIMARY KEY, batch_type NUMBER(20), [some other values] ... ); CREATE TABLE job ( job_id NUMBER(20) PRIMARY KEY, job_batch_id NUMBER(20), job_usr_id NUMBER(20), job_date DATE

假设我有两个表
job
batch

CREATE TABLE batch
(
  batch_id   NUMBER(20) PRIMARY KEY,
  batch_type NUMBER(20),
  [some other values] ...
);

CREATE TABLE job
(
  job_id NUMBER(20) PRIMARY KEY,
  job_batch_id NUMBER(20),
  job_usr_id NUMBER(20),
  job_date DATE,
  [some other values] ...
  CONSTRAINT fk_job_batch
    FOREIGN KEY (job_batch_id) REFERENCES batch(batch_id),
  CONSTRAINT fk_job_usr
    FOREIGN KEY (job_usr_id) REFERENCES client(usr_id)
);
假设它们每个都包含相当数量的数据(数百万行)。我想做的是创建一个物化视图,以反映每个
usr\u id
,为特定类型的批运行的第一个和最后一个作业。例如:

CREATE MATERIALIZED VIEW client_first_last_job
(usr_id, first_job_date, last_job_date)
AS
(
  SELECT
    job_usr_id    AS usr_id,
    MIN(job_date) AS first_job_date,
    MAX(job_date) AS last_job_date
  FROM job, batch
  WHERE job_batch_id=batch_id
    AND batch_type IN (1,3,5,9)
  GROUP BY job_usr_id
);
这一切都很好,但由于记录太多,构建这个物化视图需要很长时间(远远超过每次需要刷新时处理的时间)。我的直接想法是使用物化视图日志进行增量更新。这些都很容易创建。但是,当我尝试构建MV以使用
按需快速刷新
时,我得到了一个
ORA-12015:无法从复杂的查询创建快速刷新物化视图
错误,我猜通过一些谷歌搜索,这是由于连接函数和聚合函数共存所致


还有别的办法吗?请注意,对父表进行反规范化或其他更改是不可行的

您可以嵌套您的mviews,您可以从以下站点阅读:

验证两个MView都可以快速刷新:

exec dbms_mview.refresh('JOINMVIEW', 'C');
exec dbms_mview.refresh('JOINMVIEW', 'F');

exec dbms_mview.refresh('CLIENT_FIRST_LAST_JOB', 'C');    
exec dbms_mview.refresh('CLIENT_FIRST_LAST_JOB', 'F');

您可以将两个mview放入同一个刷新组(),只需确保按照它们的依赖关系顺序添加它们。换句话说,在本例中,在向刷新组添加客户机第一个作业和最后一个作业之前添加JOINMVIEW

JOINMVIEW
将产生一些非常严重的存储影响,即父表中约75%的行数。我不知道我是否能够合理地承诺这么多。@MikeCarCenter由于Streams复制在Oracle 11或12版本中已被弃用,我不确定您是否有Oracle Goldengate之外的其他解决方案,这是一个昂贵的额外成本选项(前提是您已经使用Enterprise Edition)。我理解。我担心会是这样的。批处理表和作业表以及生成的mview有多大?构建mview需要多长时间?@BobC数亿行。问题中的视图仅需2个多小时即可构建。一旦有机会,我将测试答案中的视图。我很好奇非原子完全刷新是否能足够快地满足您的需要:exec dbms\u mview.refresh('CLIENT\u FIRST\u LAST\u JOB','C',atomic\u refresh=>false);为了防止您不知道其局限性,非原子刷新有一个显著的回退,即在刷新过程中(甚至对其他用户和会话)表可能会显示为空。但是,由于它执行truncate+insert-append,因此运行速度会快得多;与执行删除+插入的常规完全刷新不同。
exec dbms_mview.refresh('JOINMVIEW', 'C');
exec dbms_mview.refresh('JOINMVIEW', 'F');

exec dbms_mview.refresh('CLIENT_FIRST_LAST_JOB', 'C');    
exec dbms_mview.refresh('CLIENT_FIRST_LAST_JOB', 'F');