我有一个关于 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 操作时,我需要创建一个 ON 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
为目标。更新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。