我正在尝试基于this article on valena.com模仿快照物化视图,并创建了我需要的物化视图。
我的下一个任务是在PostgreSQL中每晚执行刷新物化视图脚本。我正在使用pgAdmin并发现我需要在我的数据库服务器(Linux)上安装pgagent并通过编写pgscript在pgAdmin中创建作业。
这是我需要的,还是有更好的方法每晚运行这个脚本?
for all i in tables that begin with name 'mview_%'
SELECT refresh_matview(i);
end loop;
答案 0 :(得分:9)
我刚刚在我的crontab中添加了一个条目:
*/3 * * * * /scripts/matviewsRefresh.sh
这会每三分钟调用一次脚本,你可以调整它。
在matviewsRefresh.sh
内:
echo 'select matview_refresh_all();' | su - postgres -c "psql MYDBNAME"
当然,matview_refresh_all
是一个pl / pgsql函数,它循环遍历所有物化视图并刷新旧视图(我添加了一个辅助表,记录每个mview的上次刷新时间,每个都有不同的刷新频率)
答案 1 :(得分:3)
@leonbloy说的话。
另外,您还可以将cronjob放在postgres系统用户的 crontab 中并简化通话:
psql mydb -c 'select maint.f_mv_update()'
这适用于您可以在非工作时间锁定表格的环境。如果您没有那么奢侈,可能需要并行创建新表,然后删除原始表并重命名副本以将阻塞降至最低。
我为我的mv制度中的所有对象保留了单独的模式maint
我的功能是刷新它们:
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();