Refresh a materialized view automatically using a rule or notify

后端 未结 2 971
盖世英雄少女心
盖世英雄少女心 2020-11-27 11:14

I have a materialized view on a PostgreSQL 9.3 database which seldom changes (about twice a day). But when it does, I\'d like to update its data promptly.

Here is wha

相关标签:
2条回答
  • 2020-11-27 11:28

    PostgreSQL 9.4 added REFRESH CONCURRENTLY to Materialized Views.

    This may be what you're looking for when you describe trying to setup an asynchronous update of the materialized view.

    Users selecting from the materialized view will see incorrect data until the refresh finishes, but in many scenarios that use a materialized view, this is an acceptable tradeoff.

    Use a statement level trigger that watches the underlying tables for any changes and then refreshes the materialized view concurrently.

    0 讨论(0)
  • 2020-11-27 11:35

    You should refresh the view in triggers after insert/update/delete/truncate for each statement on table1 and table2.

    create or replace function refresh_mat_view()
    returns trigger language plpgsql
    as $$
    begin
        refresh materialized view mat_view;
        return null;
    end $$;
    
    create trigger refresh_mat_view
    after insert or update or delete or truncate
    on table1 for each statement 
    execute procedure refresh_mat_view();
    
    create trigger refresh_mat_view
    after insert or update or delete or truncate
    on table2 for each statement 
    execute procedure refresh_mat_view();
    

    In this way your materialized view is always up to date. This simple solution might be hard to accept with frequent inserts/updates and sporadic selects. In your case (seldom changes about twice a day) it ideally fits your needs.


    To realize deferred refresh of a materialized view you need one of the following features:

    • asynchronous trigger
    • trigger before select
    • rule on select before

    Postgres has none of them, so it seems that there is no clear postgres solution.

    Taking this into account I would consider a wrapper function for selects on mat_view, e.g.

    CREATE OR REPLACE FUNCTION select_from_mat_view(where_clause text)
    RETURNS SETOF mat_view AS $body$
    BEGIN
      -- here is checking whether to refresh the mat_view
      -- then return the select:
      RETURN QUERY EXECUTE FORMAT ('SELECT * FROM mat_view %s', where_clause);
    END;
    $body$ LANGUAGE plpgsql;
    

    If it is acceptable in practice depends on particulars I do not know about.

    0 讨论(0)
提交回复
热议问题