2013-11-14 12 views
8

Sto caricando un gruppo di dati in un database PostgresQL 9.3 e quindi voglio aggiornare tutte le viste materializzate che dipendono dalle tabelle aggiornate. C'è un modo per farlo automaticamente invece di passare attraverso ogni vista e rinfrescarli uno per uno? So che Oracle può farlo abbastanza facilmente ma non ho trovato nulla dopo aver letto la documentazione di PostgreSQL.Come aggiornare tutte le viste materializzate in Postgresql 9.3 in una sola volta?

+1

Controllare pg_matviews, selezionare tutte le visualizzazioni necessarie e eseguire un aggiornamento. Potresti scrivere una funzione per questo. –

+0

sembra come scrivere la mia funzione è l'unica opzione con la versione corrente – srk

risposta

18

Assomiglia attuale versione di PostgreSQL (9.3.1) non ha tale funzionalità, hanno dovuto scrivere la mia funzione invece:

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; 

(su GitHub: https://github.com/sorokine/RefreshAllMaterializedViews)

+1

Ora con il supporto della parola chiave ["CONCURRENTLY"] (https://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.4#REFRESH_MATERIALIZED_VIEW_CONCURRENTLY) in 9.4, sarebbe interessante per te utilizzarlo per impedire il blocco del tavolo? –

+0

Voglio esaminarlo non appena ho messo le mani su 9.4 installazione. Penso che sarà un'aggiunta conveniente. – srk

+2

Oggi ho inserito il codice nel ramo principale di https://github.com/sorokine/RefreshAllMaterializedViews che esegue aggiornamenti simultanei. – srk

1

stesso metodo, aggiunto il controllo standby

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

stesso metodo, aggiunta l'opzione per eseguirlo su tutti gli schemi, facoltativamente contemporaneamente.

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; 

Ho messo su GitHub: https://github.com/frankhommers/RefreshAllMaterializedViews

1

Il frammento di seguito utilizza REFRESH MATERIALIZED VIEW CONCURRENTLY quando esiste un indice UNIQUE per quella vista.

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; 

Questo frammento accetta un nome di schema per limitare i punti di vista che sono rinfrescati.

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; 
Problemi correlati