use*_*760 41 postgresql materialized-view postgresql-9.3 postgresql-9.4
是否可以在 PostgreSQL 中增量刷新物化视图,即仅针对新的或已更改的数据?
考虑这个表和物化视图:
CREATE TABLE graph (
xaxis integer NOT NULL,
value integer NOT NULL,
);
CREATE MATERIALIZED VIEW graph_avg AS
SELECT xaxis, AVG(value)
FROM graph
GROUP BY xaxis
Run Code Online (Sandbox Code Playgroud)
定期添加新值graph或更新现有值。我想graph_avg每隔几个小时刷新一次视图,仅针对已更新的值。但是在 PostgreSQL 9.3 中,整个表都被刷新了。这是相当耗时的。下一个版本 9.4 允许CONCURRENT更新但它仍然刷新整个视图。有数以百万计的行,这需要几分钟。
跟踪更新和新值并仅部分刷新视图的好方法是什么?
Erw*_*ter 27
您始终可以实现自己的表作为“物化视图”。这就是我们之前MATERIALIZED VIEW在 Postgres 9.3 中实现的方式。
您可以创建一个普通的VIEW:
CREATE VIEW graph_avg_view AS
SELECT xaxis, AVG(value) AS avg_val
FROM graph
GROUP BY xaxis;
Run Code Online (Sandbox Code Playgroud)
并在您需要重新开始时实现一次或任何时候的结果:
CREATE TABLE graph_avg AS
SELECT * FROM graph_avg_view;
Run Code Online (Sandbox Code Playgroud)
(或者使用SELECT直接的语句,而无需创建一个VIEW。)
然后,根据您的使用情况未透露细节,你可以DELETE/ UPDATE/INSERT手动更改。
带有数据修改 CTE 的基本 DML 语句,如下所示:
假设没有其他人试图写入到graph_avg并行(阅读是没有问题的):
WITH del AS (
DELETE FROM graph_avg t
WHERE NOT EXISTS (SELECT FROM graph_avg_view WHERE xaxis = t.xaxis)
)
, upd AS (
UPDATE graph_avg t
SET avg_val = v.avg_val
FROM graph_avg_view v
WHERE t.xaxis = v.xaxis
AND t.avg_val <> v.avg_val
-- AND t.avg_val IS DISTINCT FROM v.avg_val -- alt if avg_val can be NULL
)
INSERT INTO graph_avg t -- no target list, whole row
SELECT v.*
FROM graph_avg_view v
WHERE NOT EXISTS (SELECT FROM graph_avg WHERE xaxis = v.xaxis);
Run Code Online (Sandbox Code Playgroud)
timestamp默认列添加now()到您的基表。让我们称之为ts。
xaxis或value。创建一个小表来记住最新快照的时间戳。让我们称之为mv:
CREATE TABLE mv (
tbl text PRIMARY KEY
, ts timestamp NOT NULL DEFAULT '-infinity'
); -- possibly more details
Run Code Online (Sandbox Code Playgroud)创建此部分多列索引:
CREATE INDEX graph_mv_latest ON graph (xaxis, value)
WHERE ts >= '-infinity';
Run Code Online (Sandbox Code Playgroud)使用上一个快照的时间戳作为查询中的谓词,以完美的索引使用刷新快照。
在事务结束时,删除索引并使用事务时间戳替换索引谓词(最初'-infinity')中的时间戳重新创建它 ,您也将其保存到表中。一切都在一笔交易中。
请注意,部分索引非常适合覆盖INSERT和UPDATE操作,但不是DELETE. 为了解决这个问题,您需要考虑整个表格。这一切都取决于确切的要求。
Bas*_*que 19
虽然不是您要求的增量更新,但 Postgres 9.4 确实提供了新的并发更新功能。
引用文档...
在 PostgreSQL 9.4 之前,刷新物化视图意味着锁定整个表,因此阻止任何查询它,并且如果刷新需要很长时间才能获取排他锁(当它等待使用它的查询完成时),它反过来正在阻止后续查询。现在可以使用 CONCURRENTLY 关键字来缓解这种情况:
postgres=# REFRESH MATERIALIZED VIEW CONCURRENTLY mv_data;
Run Code Online (Sandbox Code Playgroud)
但是,物化视图上需要存在唯一索引。它不是锁定物化视图,而是创建它的临时更新版本,比较两个版本,然后对物化视图应用 INSERT 和 DELETE 以应用差异。这意味着查询在更新时仍然可以使用物化视图。与它的非并发形式不同,元组不会被冻结,并且由于前面提到的 DELETE 会留下死元组,因此它需要 VACUUMing。
此并发更新仍在执行完整的新查询(不是增量查询)。因此 CONCURRENTLY 不会节省整体计算时间,它只会最大限度地减少物化视图在更新期间不可用的时间。
| 归档时间: |
|
| 查看次数: |
26525 次 |
| 最近记录: |