在 Postgres 中使用物化视图的最佳实践

nda*_*son 6 postgresql

作为背景,我使用了许多基于 PostGIS 空间查询的物化视图,其中一些需要数天才能刷新(只要底层空间数据(即道路网络)更新,这些视图就很少刷新)。然后,我还有许多其他视图,它们依赖于这些物化视图。

虽然使用物化视图通常效果很好,但当我需要更改其中一个视图的定义(例如,更改连接条件或添加新列)时,它就变成了一场噩梦。由于没有CREATE OR REPLACE ...物化视图的等价物,我最终不得不删除然后重新创建所有依赖对象。

最近,我开始将我所有的物化视图“包装”在标准视图中,以此来解决这个问题。所以基本上每个物化视图都有一个相应的标准视图,它直接从物化视图中选择所有列。然后没有依赖项直接引用物化视图,他们只引用包装视图。这允许我临时替换包装器的定义以指向不同的数据源(不是物化视图),因此我可以更改物化视图的定义,然后最后将包装器重定向回物化视图。呼!它可以工作,并且避免了级联删除/重新创建对象过程的需要,但看起来仍然很笨拙。

是否有使用物化视图来克服这些限制的最佳实践过程?在这里避免级联删除/重新创建步骤的常用方法是什么?

Eze*_*nay 0

我使用许多作为安装包的脚本,并从 PgAdminIII 打开并运行。例如,其中之一是我所有的物化视图,以及CREATE OR REPLACE权限分配等。另一个是用于创建或更改表的脚本:

CREATE TABLE IF NOT EXISTS mytable (myfield serial int);

DO $$BEGIN IF NOT EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = 'mytable'::regclass AND attname = 'newfield') THEN
  ALTER TABLE mytable ADD newfield type; END IF;
END;$$;

DO $$BEGIN IF EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = 'mytable'::regclass AND attname = 'oldfield') THEN
  ALTER TABLE mytable DROP oldfield CASCADE;
END;$$;
Run Code Online (Sandbox Code Playgroud)

因此,我会打开更改表脚本,在脚本的某处或末尾添加更改,运行它,然后如果存在级联删除或影响其他对象,请打开这些对象的脚本并重新运行它。请注意,在 24/7 系统上以这种方式运行脚本可能会导致几秒钟的停机/失败,因此最好准备一个单独的脚本,其中包含要立即运行的所有修改。