微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Postgres 触发刷新物化视图一段时间后不起作用

如何解决Postgres 触发刷新物化视图一段时间后不起作用

我创建了一个物化视图和一个触发器,用于在对源表进行任何更新后刷新它。

似乎一切正常,但一段时间后似乎触发器停止工作,因为物化视图仍然保留陈旧数据。

在我重新创建触发器后的某个时刻,该功能再次开始工作。

11 中使用的 postgres 版本。

CREATE OR REPLACE FUNCTION refresh_some_view()
    RETURNS TRIGGER
    LANGUAGE PLPGsql
AS
$$
BEGIN
    REFRESH MATERIALIZED VIEW some_view;
    RETURN NEW;
END;
$$;


CREATE TRIGGER on_source_table_update
    AFTER UPDATE OR INSERT OR DELETE
    ON source_table
    FOR EACH ROW
EXECUTE PROCEDURE refresh_some_view();

解决方法

使用 FOR EACH STATEMENT 而不是 FOR EACH ROW。这将阻止在插入语句的每一行之后刷新视图,这很可能不是您想要的。

CREATE TRIGGER on_source_table_update 
AFTER UPDATE OR INSERT OR DELETE ON source_table 
FOR EACH STATEMENT EXECUTE PROCEDURE refresh_some_view();

您可以在查询规划器中查看。如果您使用 FOR EACH STATEMENT,则函数中的刷新将仅被调用一次 - 请参阅 Trigger on_source_table_update 处的调用次数。此查询计划显示了包含 1000 行的插入会发生什么 - 请参阅 rows 处的数字 ProjectSet

                                QUERY PLAN 
------------------------------------------------------------------------------

Insert on source_table (actual time=7.097..7.140 rows=0 loops=1)
  ->  ProjectSet (actual time=0.005..0.398 rows=1000 loops=1)
        ->  Result (actual time=0.002..0.044 rows=1 loops=1)
Planning Time: 0.264 ms
Trigger on_source_table_update: time=11.628 calls=1
Execution Time: 19.011 ms

...但是如果你坚持 FOR EACH ROW 事情会变得更慢,因为触发器每行调用一次函数(1000 次!):

                                QUERY PLAN 
------------------------------------------------------------------------------
Insert on source_table (actual time=4.187..4.188 rows=0 loops=1)
  ->  ProjectSet (actual time=0.004..0.204 rows=1000 loops=1)
        ->  Result (actual time=0.002..0.002 rows=1 loops=1)
Planning Time: 0.122 ms
Trigger on_source_table_update: time=13815.499 calls=1000
Execution Time: 13820.529 ms

演示:PIL

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。