【发布时间】:2014-07-17 09:39:51
【问题描述】:
我有一个很少更改(大约一天两次)的 PostgreSQL 9.3 数据库的物化视图。但是当它发生时,我想及时更新它的数据。
到目前为止,这是我的想法:
有一个物化视图mat_view,它使用一些连接语句从表table1 和table2 中获取数据。
每当table1 或table2 中的某些内容发生变化时,我已经有一个触发器来更新一个小配置表config,其中包含
table_name | mat_view_name | need_update
-----------+---------------+------------
table1 | mat_view | TRUE/FALSE
table2 | mat_view | TRUE/FALSE
因此,如果table1 中的任何内容发生变化(每个语句的 UPDATE 和 DELETE 触发器都有一个触发器),则第一行中的字段 need_update 将设置为 TRUE。
table2 和第二行也是如此。
显然,如果need_update 为TRUE,则必须刷新物化视图。
更新:
由于物化视图不支持规则(正如@pozs 在下面的评论中提到的那样),我会更进一步。我会用定义“SELECT * FROM mat_view”创建一个虚拟视图v_mat_view。当用户在此视图上执行 SELECT 时,我需要在 SELECT 上创建一个规则,它执行以下操作:
- 检查
mat_view是否应该更新(SELECT 1 FROM config WHERE mat_view_name='mat_view' AND need_update=TRUE) - 用
UPDATE config SET need_update=FALSE where mat_view_name='mat_view'重置need_update标志 REFRESH MATERIALIZED VIEW mat_view- 最后以
mat_view为目标执行原始SELECT 语句。
更新2: 我尝试创建上述步骤:
创建一个处理上述四点的函数:
CREATE OR REPLACE FUNCTION mat_view_selector()
RETURNS SETOF mat_view AS $body$
BEGIN
-- here is checking whether to refresh the mat_view
-- then return the select:
RETURN QUERY SELECT * FROM mat_view;
END;
$body$ LANGUAGE plpgsql;
创建真正从函数mat_view_selector中选择的视图v_mat_view:
CREATE TABLE v_mat_view AS SELECT * from mat_view LIMIT 1;
DELETE FROM v_mat_view;
CREATE RULE "_RETURN" AS
ON SELECT TO v_mat_view
DO INSTEAD
SELECT * FROM mat_view_selector();
-- this also converts the empty table 'v_mat_view' into a view.
结果不满意:
# explain analyze select field1 from v_mat_view where field2 = 44;
QUERY PLAN
Function Scan on mat_view_selector (cost=0.25..12.75 rows=5 width=4)
(actual time=15.457..18.048 rows=1 loops=1)
Filter: (field2 = 44)
Rows Removed by Filter: 20021
Total runtime: 31.753 ms
与从 mat_view 本身进行选择相比:
# explain analyze select field1 from mat_view where field2 = 44;
QUERY PLAN
Index Scan using mat_view_field2 on mat_view (cost=0.29..8.30 rows=1 width=4)
(actual time=0.015..0.016 rows=1 loops=1)
Index Cond: (field2 = 44)
Total runtime: 0.036 ms
所以基本上它确实有效,但性能可能是个问题。
有人有更好的主意吗? 如果没有,那么我将不得不在应用程序逻辑中以某种方式实现它,或者更糟:运行一个每分钟左右运行的简单 cronjob。
【问题讨论】:
-
有趣的方法。您是否尝试过替换视图的
"_RETURN"规则?应该很简单postgresql.org/docs/current/static/sql-createrule.html -
你能改写你的问题并详细说明一下吗?即使阅读了您发布的链接,我也不明白您的意思。
-
视图默认有一个
"_RETURN"规则。您想在返回视图的原始选择之前替换它以刷新您的物化视图。你试过了吗? -
没关系,在物化视图上重新定义规则(存在!)会出现错误
rules on materialized views are not supported SQL state: 0A000
标签: postgresql triggers postgresql-9.3 materialized-views