是否可以在 PostgreSQL 中部分刷新物化视图?

Posted

技术标签:

【中文标题】是否可以在 PostgreSQL 中部分刷新物化视图?【英文标题】:Is it possible to partially refresh a materialized view in PostgreSQL? 【发布时间】:2014-10-27 18:32:12 【问题描述】:

In Oracle, it is possible to refresh just part of the data。但是在 PostgreSQL 中,从 9.3(现在的当前版本)开始支持物化视图,时间不长。所以我想知道:是否可以在 PostgreSQL 9.3 的物化视图中只刷新部分数据?如果是,怎么做?

【问题讨论】:

你能举例说明你的意思吗?我认为物化视图的目的是只显示部分数据。 您链接到 Oracle 的那个答案不是很引人注目。它说您可以强制将其中一个分区换成已分区的 MV。由于 Postgresql 中的分区并不是真正的内置功能,而是您自己推出的功能,我想您也可以在 Postgres 中使用相同的方法。 【参考方案1】:

PostgreSQL 还不支持物化视图的渐进式/部分更新。

9.4 添加了REFRESH MATERIALIZED VIEW CONCURRENTLY,但仍需完全重新生成。

如果有人足够热情,希望我们能在 9.5 中看到支持。但是,对于简单的物化视图,只有在没有用户定义的触发器/规则的情况下才能做到这一点,并且需要特殊的支持来处理诸如 count(...) ... GROUP BY ... 的增量更新之类的事情。

不过,您提到的 Oracle 答案实际上并不是增量刷新。它是按分区刷新的。要让 PostgreSQL 在本机上支持这一点,它首先必须支持真正的声明式分区——它不支持,尽管我们正在讨论它是否可以在 9.5 中完成。

【讨论】:

值得一提的是这个新功能正在开发中:wiki.postgresql.org/wiki/Incremental_View_Maintenance【参考方案2】:

我刚刚遇到了类似的问题。从Craig's answer 得知这是不可能的,我使用了一种解决方法。我解构了物化视图,并在VIEW 中加入和/或合并了各个部分:

    为每个有问题的行或列组创建一个MATERIALIZED VIEWmaterial_col1material_col2 等或更复杂的分离 where 条件),使用例如一个常见的id 列。 在id 列上使用常规VIEW (fake_materialized_view) joinMATERIALIZED VIEWs 表 对于不相交的行,必须union all他们 REFRESH MATERIALIZED VIEW 根据需要 改用fake_materialized_view 上的查询

VIEW 看起来有点像这样:

CREATE VIEW fake_materialized_view AS 

  SELECT m1.id, m1.col1, m2.col2
  FROM material_col1 as m1 LEFT JOIN 
       material_col2 as m2 
         ON m1.id = m2.id

  -- in case of additional row partitioning, e.g.
  -- UNION ALL SELECT m3.id, m3.col1, m3.col2
  -- FROM material_col3 m3

(Upd1:感谢 Barry 的 comment 利用行分区,我将其添加到答案中。)

【讨论】:

不幸的是,这只对“分区列”有用,而不是“分区行”(不一定映射到简单的可定义分区,而是映射到单个行) @AndreasDietrich 在一堆物化视图上使用union all,每个分区一个,如果分区列表相对固定,可以正常工作。它不会对每个用例都有帮助,但它可以很好地用于聚合的物化视图。 @n1000: 嘿,我刚刚意识到,我编辑了你的答案,我认为这是我的:/ ...抱歉,如果编辑对你不利...那么让我们恢复它并我将发布一个带有示例的自己的版本作为单独的答案。

以上是关于是否可以在 PostgreSQL 中部分刷新物化视图?的主要内容,如果未能解决你的问题,请参考以下文章

如何一次刷新 Postgresql 9.3 中的所有物化视图?

PostgreSQL定时刷新物化视图的一种简单方法

PG 物化视图

Oracle 11x 中增量刷新的物化视图和相应的主表日志

并发刷新物化视图

刷新物化视图:并发、事务行为