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

时间:2017-02-27 20:32:14

标签: oracle materialized-views

假设我有两个表jobbatch

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_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
);

这一切都很好,但是因为有很多记录需要很长时间来构建这个物化视图(远远超过每次需要刷新时可以接受的时间)。我的直接想法是使用Materialized View Logs进行增量更新。这些很容易创建。但是当我尝试构建MV以使用REFRESH FAST ON DEMAND时,这会给我一个ORA-12015: cannot create a fast refresh materialized view from a complex query错误,我猜测这是因为连接和聚合函数共存所带来的一些谷歌搜索。

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

1 个答案:

答案 0 :(得分:2)

您可以在docs

中嵌套您可以阅读的mviews
CREATE MATERIALIZED VIEW joinmview
(usr_id, job_date)
REFRESH FORCE ON DEMAND
AS
(
  SELECT
    job_usr_id    AS usr_id,
    job_date
  FROM job, batch
  WHERE job_batch_id=batch_id
    AND batch_type IN (1,3,5,9)
);

CREATE MATERIALIZED VIEW LOG ON JOINMVIEW 
  WITH ROWID (usr_id, JOB_DATE) including new values;

CREATE MATERIALIZED VIEW client_first_last_job
(usr_id, first_job_date, last_job_date)
REFRESH FORCE ON DEMAND
AS
(
  SELECT
    usr_id,
    MIN(job_date) AS first_job_date,
    MAX(job_date) AS last_job_date
  FROM joinmview
  GROUP BY usr_id
);

验证两个mviews是否可以快速刷新:

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');

您可以将两个mviews放入同一个刷新组(docs),只需确保按照依赖关系顺序添加它们。换句话说,在此示例中,在之前添加JOINMVIEW ,将CLIENT_FIRST_LAST_JOB添加到刷新组。