如何立即刷新Postgresql 9.3中的所有物化视图?

srk*_*srk 17 postgresql materialized-views postgresql-9.3

我正在将一堆数据加载到PostgresQL 9.3数据库中,然后我想刷新所有依赖于更新表的物化视图.有没有办法自动完成而不是浏览每个视图并逐个刷新?我知道Oracle可以很容易地做到这一点但是在梳理完PostgreSQL文档后我没有找到任何东西.

srk*_*srk 26

看起来当前版本的PostgreSQL(9.3.1)没有这样的功能,不得不编写我自己的函数:

CREATE OR REPLACE FUNCTION RefreshAllMaterializedViews(schema_arg TEXT DEFAULT 'public')
RETURNS INT AS $$
DECLARE
    r RECORD;
BEGIN
    RAISE NOTICE 'Refreshing materialized view in schema %', schema_arg;
    FOR r IN SELECT matviewname FROM pg_matviews WHERE schemaname = schema_arg 
    LOOP
        RAISE NOTICE 'Refreshing %.%', schema_arg, r.matviewname;
        EXECUTE 'REFRESH MATERIALIZED VIEW ' || schema_arg || '.' || r.matviewname; 
    END LOOP;

    RETURN 1;
END 
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

(在github上:https://github.com/sorokine/RefreshAllMaterializedViews)

  • 请注意,如果某些物化视图依赖于其他物种,那么它们运行的​​顺序就很重要.这个脚本没有考虑到这一点.如果你有这样的情况,你需要做一些更复杂的事情. (3认同)
  • 今天我把代码拉到https://github.com/sorokine/RefreshAllMaterializedViews的主分支中,执行并发更新. (2认同)
  • 这是一个SQL,它找到不能同时刷新的物化视图(因为缺少UNIQUE索引):http://dba.stackexchange.com/a/101938/8607我将两个脚本作为一个团队使用. (2认同)

use*_*015 7

如果实例化视图彼此不依赖,则上述答案可以正常工作。如果不是这种情况,则刷新实例化视图的顺序很重要(即,在刷新需要依赖的实例化视图之前,需要刷新不依赖于任何其他实例化视图的实例化视图)。下面的代码将生成一个物化视图的有序列表,以便可以正确的顺序对其进行更新。

CREATE OR REPLACE VIEW mat_view_dependencies AS
WITH RECURSIVE s(start_schemaname,start_mvname,schemaname,mvname,relkind,
               mvoid,depth) AS (
-- List of mat views -- with no dependencies
SELECT n.nspname AS start_schemaname, c.relname AS start_mvname,
n.nspname AS schemaname, c.relname AS mvname, c.relkind,
c.oid AS mvoid, 0 AS depth
FROM pg_class c JOIN pg_namespace n ON c.relnamespace=n.oid
WHERE c.relkind='m'
UNION
-- Recursively find all things depending on previous level
SELECT s.start_schemaname, s.start_mvname,
n.nspname AS schemaname, c.relname AS mvname,
c.relkind,
c.oid AS mvoid, depth+1 AS depth
FROM s
JOIN pg_depend d ON s.mvoid=d.refobjid
JOIN pg_rewrite r ON d.objid=r.oid
JOIN pg_class c ON r.ev_class=c.oid AND (c.relkind IN ('m','v'))
JOIN pg_namespace n ON n.oid=c.relnamespace
WHERE s.mvoid <> c.oid -- exclude the current MV which always depends on itself
)
SELECT * FROM s;

CREATE OR REPLACE VIEW mat_view_refresh_order AS
WITH b AS (
-- Select the highest depth of each mat view name
SELECT DISTINCT ON (schemaname,mvname) schemaname, mvname, depth
FROM mat_view_dependencies
WHERE relkind='m'
ORDER BY schemaname, mvname, depth DESC
)
-- Reorder appropriately
SELECT schemaname, mvname, depth AS refresh_order
FROM b
ORDER BY depth, schemaname, mvname
;
Run Code Online (Sandbox Code Playgroud)

可以用来psql按适当的顺序刷新所有视图,如下所示:

WITH a AS (
SELECT 'REFRESH MATERIALIZED VIEW "' || schemaname || '"."' || mvname || '";' AS r
FROM mat_view_refresh_order
ORDER BY refresh_order
)
SELECT string_agg(r,E'\n') AS script FROM a \gset

\echo :script
:script
Run Code Online (Sandbox Code Playgroud)

可以将最后一部分转换为函数,如先前解决方案中所做的那样。