我有两张桌子,一张父表和一张子表。 父表和子表通过外键链接在一起。 父表和子表都有自己的主键。
create table parent (
parent_id integer primary key,
data ...
);
create table child(
child_id integer primary key,
parent_id integer references parent(parent_id),
data ...
);
我想制作一对物化视图来存储父表和子表的数据副本,所以我制作了2个物化视图。
create materialized view view_parent as select * from parent;
create unique index on view_parent(parent_id);
create materialized view view_child as select * from child;
create unique index on view_child(child_id);
现在,当我决定刷新视图时,我预见的问题是,如果您根据刷新物化视图的顺序不断添加到基表,您可能会获得没有父级的子行(如果您先添加父级) )或没有子项的父行(如果您先处理子项)。 删除可能会导致两个表之间出现类似的问题。
我认为可以避免这种情况的一种方法是在事务中进行刷新,因为至少如果您这样做,刷新应该在其开发的同一阶段查看父表,但是这会锁定多少系统? 理想情况下,我希望对两个父表进行快照并刷新物化视图,允许用户查看物化视图而不锁定它们,并允许写入父表,同样也不将用户锁定。 在事务中刷新物化视图是否会锁定物化视图的读取器或父表的写入器?
您可以创建单个物化视图:
CREATE MATERIALIZED VIEW parent_child_view AS
SELECT parent_id, parent_data,
child_id, child_data
FROM parent
JOIN child USING (parent_id);
CREATE UNIQUE INDEX ON parent_child_view (parent_id, child_id);
然后您可以创建视图:
CREATE VIEW parent_view AS
SELECT DISTINCT parent_id, parent_data
FROM parent_child_view;
CREATE VIEW child_view AS
SELECT DISTINCT child_id, child_data
FROM parent_child_view;
这将使观点一致。
但是如果表很大,由于
DISTINCT
和 parent_child_view
的大小,性能不会很好。如果您想要的只是一个抽象层,我建议您创建视图而不是物化视图。如果您担心表锁,请确保您的事务很短,那么锁就不会成为问题。