Выполнение скрипта PostgreSQL каждую ночь

Я пытаюсь имитировать моментальный снимок материализованного представления на основе этой статьи о valena .com и создали нужные мне материализованные представления.

Моя следующая задача — каждую ночь выполнять сценарии обновления материализованных представлений в PostgreSQL. Я использую pgAdmin и обнаружил, что мне нужно установить pgagent на моем сервере базы данных (Linux) и создавать задания в pgAdmin, написав pgscript.

Это то, что мне нужно, или есть лучший способ запускать этот скрипт каждую ночь?

 for all i in tables that begin with name 'mview_%'
   SELECT refresh_matview(i);
 end loop;

person cableload    schedule 23.04.2012    source источник


Ответы (2)


Я только что поместил запись в свой crontab:

*/3 * * * * /scripts/matviewsRefresh.sh 

Это вызывает скрипт каждые три минуты, вы можете настроить это. А внутри matviewsRefresh.sh:

  echo 'select matview_refresh_all();' | su - postgres -c "psql MYDBNAME"

Конечно, matview_refresh_all — это функция pl/pgsql, которая перебирает все мои материализованные представления и обновляет старые (я добавил вспомогательную таблицу, которая записывает время последнего обновления для каждого mview, и у каждого из них разная частота обновления).

person leonbloy    schedule 23.04.2012
comment
Спасибо, leonbloy.. это так же просто, как то, что я ищу.. помощь очень ценится. - person cableload; 23.04.2012

Крон работа

Что сказал @leonbloy.

Кроме того, вы также можете поместить cronjob в crontab пользователя вашей системы postgres и упростить вызов:

psql mydb -c 'select maint.f_mv_update()' 

Автоматическое обновление материализованных представлений

Это предназначено для среды, где вы можете позволить себе ненадолго заблокировать столы в нерабочее время. Если у вас нет такой роскоши, вы можете создать новые таблицы параллельно, а затем удалить оригинал и переименовать копию, чтобы свести блокировку к минимуму.

Я сохраняю отдельную схему maint для всех объектов в моем режиме mv.
Моя функция для их обновления:

CREATE OR REPLACE FUNCTION maint.f_mv_update()
  RETURNS void AS
$func$
DECLARE
   _r    record;
BEGIN

SET LOCAL work_mem='256MB';               -- more memory for sorting et al?
SET LOCAL client_min_messages=warning;    -- suppress index creation notices

-- With concurrent load you may need to lock some tables to avoid deadlocks
-- LOCK tbl1, tbl2;

FOR _r IN
   -- cast to regclass asserts table name is valid
   SELECT (mv_schema || '.' || mv_tab)::regclass AS tbl 
         ,drop_index
         ,mv_query
         ,create_index
   FROM   maint.mv
   WHERE  active
   ORDER  BY mv_id
LOOP
   IF _r.drop_index IS NOT NULL THEN      -- drop indexes (for performance!)
      EXECUTE _r.drop_index;
   END IF;

   EXECUTE 'TRUNCATE TABLE '   || _r.tbl;
   EXECUTE 'INSERT INTO '      || _r.tbl || ' ' || _r.mv_query;

   IF _r.create_index IS NOT NULL THEN    -- recreate Indexes (also CLUSTER?)
      EXECUTE _r.create_index;
   END IF;

   EXECUTE 'ANALYZE ' || _r.tbl;          -- ANALYZE to refresh statistics
END LOOP;

RESET client_min_messages;

UPDATE maint.mv
SET last_up = localtimestamp(0) WHERE active; -- remember update

END
$func$ LANGUAGE plpgsql VOLATILE SET search_path=maint,pg_temp;

REVOKE ALL ON FUNCTION maint.f_mv_update() FROM public;

COMMENT ON FUNCTION maint.f_mv_update() IS 'Update materialized Views.
Uses table maint.mv';

В сочетании с этой таблицей, где регистрируются все материализованные представления, которые хотят принадлежать этому режиму.

CREATE TABLE maint.mv
(
  mv_id integer PRIMARY KEY, -- surrogate primary key...
  active boolean NOT NULL DEFAULT true,
  last_up timestamp(0) NOT NULL DEFAULT '2000-1-1 0:0'::timestamp, -- last update
  log_up timestamp(0) NOT NULL DEFAULT now()::timestamp(0), -- last change of row
  mv_schema text NOT NULL, -- Schema of mv table
  mv_tab text NOT NULL, -- Name of mv table
  mv_query text NOT NULL, -- SQL-query to fill mv
  drop_index text, -- SQL to drop indexes before refill
  create_index text, -- SQL to recreate indexes after refill
  note text
);
REVOKE ALL ON TABLE maint.mv FROM public;

Пример строки:

INSERT INTO maint.mv
       (mv_id, mv_schema, mv_tab, mv_query, drop_index, create_index)
VALUES ( 17, 'mv', 'mytbl'
       ,'SELECT mytbl_id, count(*) FROM mytbl GROUP BY 1;'
       ,'DROP INDEX IF EXISTS mv.mytbl_mytbl_id_idx;'
       ,'CREATE INDEX mytbl_mytbl_id_idx ON mv.mytbl (my_tbl_id);');

Вызов:

SELECT maint.f_mv_update();
person Erwin Brandstetter    schedule 23.04.2012
comment
+1 Обратите внимание, однако, что TRUNCATE быстрее, но менее безопасен, чем DELETE, в отношении параллелизма. Я не уверен, что этот подход не может привести к тому, что какая-то параллельная транзакция увидит пустое материализованное представление. - person leonbloy; 24.04.2012