2013-11-14 65 views
8

我正在將一堆數據加載到Postgresql 9.3數據庫中,然後我想刷新所有依賴於更新表的物化視圖。有沒有辦法自動執行它,而不是通過每個視圖並逐一刷新它們?我知道Oracle可以很容易地做到這一點,但在梳理PostgreSQL文檔後我沒有發現任何東西。如何一次刷新Postgresql 9.3中的所有物化視圖?

+1

檢查pg_matviews,選擇您需要的所有視圖並進行刷新。你可以爲此寫一個函數。 –

+0

看起來像寫我自己的功能是唯一的選擇與當前版本 – srk

回答

18

看起來像當前版本的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; 

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

+1

現在支持[「CONCURRENTLY」](https://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.4#REFRESH_MATERIALIZED_VIEW_CONCURRENTLY)關鍵字9.4,你是否有興趣使用它來防止表鎖定? –

+0

我想在9.4安裝完成後立即查看。我認爲這將是一個方便的補充。 – srk

+2

今天我已經將代碼拉入https://github.com/sorokine/RefreshAllMaterializedViews的master分支,它執行併發更新。 – srk

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; 
    if pg_is_in_recovery() then 
    return 1; 
    else 
    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; 
    end if; 
    RETURN 1; 
END 
$$ LANGUAGE plpgsql; 
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; 
    if pg_is_in_recovery() then 
    return 1; 
    else 
    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; 
    end if; 
    RETURN 1; 
END 
$$ LANGUAGE plpgsql; 
2

相同的方法,添加了在所有架構上運行它的選項,可以同時運行。

CREATE OR REPLACE FUNCTION RefreshAllMaterializedViews(_schema TEXT DEFAULT '*', _concurrently BOOLEAN DEFAULT false) 
RETURNS INT AS $$ 
    DECLARE 
    r RECORD; 
    BEGIN 
    RAISE NOTICE 'Refreshing materialized view(s) in % %', CASE WHEN _schema = '*' THEN ' all schemas' ELSE 'schema "'|| _schema || '"' END, CASE WHEN _concurrently THEN 'concurrently' ELSE '' END; 
    IF pg_is_in_recovery() THEN 
     RETURN 0; 
    ELSE  
     FOR r IN SELECT schemaname, matviewname FROM pg_matviews WHERE schemaname = _schema OR _schema = '*' 
     LOOP 
     RAISE NOTICE 'Refreshing %.%', r.schemaname, r.matviewname; 
     EXECUTE 'REFRESH MATERIALIZED VIEW ' || CASE WHEN _concurrently THEN 'CONCURRENTLY ' ELSE '' END || '"' || r.schemaname || '"."' || r.matviewname || '"'; 
     END LOOP; 
    END IF; 
    RETURN 1; 
    END 
$$ LANGUAGE plpgsql; 

我也把它在GitHub上:https://github.com/frankhommers/RefreshAllMaterializedViews

1

的片段下方使用REFRESH MATERIALIZED VIEW CONCURRENTLYUNIQUE指數存在這一觀點。

CREATE OR REPLACE FUNCTION public.refresh_materialized_views() 
    RETURNS void 
AS 
$BODY$ 
    DECLARE 
     refresh_sql text; 
    BEGIN 

    WITH matviews AS (
     SELECT t.oid, 
       relname AS view_name, 
       nspname AS schema_name 
     FROM pg_class t 
     JOIN pg_catalog.pg_namespace n ON n.oid = t.relnamespace 
     WHERE t.relkind = 'm' 
      AND nspname NOT LIKE 'pg-%' 
    ), unique_indexes AS (
    SELECT m.oid, 
      view_name, 
      schema_name 
     FROM pg_class i, 
      pg_index ix, 
      matviews m 
     WHERE ix.indisunique = true 
     AND ix.indexrelid = i.oid 
     AND ix.indrelid = m.oid 
    ), refresh_concurrently AS (
     SELECT 'REFRESH MATERIALIZED VIEW CONCURRENTLY ' || quote_ident(schema_name) || '.' || quote_ident(view_name) AS sql 
     FROM unique_indexes 
    ), refresh AS (
     SELECT 'REFRESH MATERIALIZED VIEW ' || quote_ident(schema_name) || '.' || quote_ident(view_name) AS sql 
     FROM matviews 
     WHERE oid != all (SELECT oid FROM unique_indexes) 
    ), sql AS (
     SELECT sql FROM refresh_concurrently 
     UNION ALL 
     SELECT sql FROM refresh 
    ) 

    SELECT string_agg(sql, E';\n') || E';\n' FROM sql INTO refresh_sql; 

    EXECUTE refresh_sql; 

    END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE; 

此代碼段接受模式名稱以限制刷新的視圖。

CREATE OR REPLACE FUNCTION public.refresh_materialized_views(_schema text) 
    RETURNS void 
AS 
$BODY$ 
    DECLARE 
     refresh_sql text; 
    BEGIN 

    WITH matviews AS (
     SELECT t.oid, 
       relname AS view_name, 
       nspname AS schema_name 
     FROM pg_class t 
     JOIN pg_catalog.pg_namespace n ON n.oid = t.relnamespace 
     WHERE t.relkind = 'm' 
      AND nspname NOT LIKE 'pg-%' 
      AND nspname = _schema 
    ), unique_indexes AS (
    SELECT m.oid, 
      view_name, 
      schema_name 
     FROM pg_class i, 
      pg_index ix, 
      matviews m 
     WHERE ix.indisunique = true 
     AND ix.indexrelid = i.oid 
     AND ix.indrelid = m.oid 
    ), refresh_concurrently AS (
     SELECT 'REFRESH MATERIALIZED VIEW CONCURRENTLY ' || quote_ident(schema_name) || '.' || quote_ident(view_name) AS sql 
     FROM unique_indexes 
    ), refresh AS (
     SELECT 'REFRESH MATERIALIZED VIEW ' || quote_ident(schema_name) || '.' || quote_ident(view_name) AS sql 
     FROM matviews 
     WHERE oid != all (SELECT oid FROM unique_indexes) 
    ), sql AS (
     SELECT sql FROM refresh_concurrently 
     UNION ALL 
     SELECT sql FROM refresh 
    ) 

    SELECT string_agg(sql, E';\n') || E';\n' FROM sql INTO refresh_sql; 

    EXECUTE refresh_sql; 

    END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE;