pg_ivm

pg_ivm

PostgreSQL增量视图维护扩展模块

pg_ivm是PostgreSQL的增量视图维护扩展模块,支持物化视图实时更新而无需完全重新计算。兼容PostgreSQL 13至17版本,支持内连接、DISTINCT、部分聚合函数和简单子查询。通过自动创建触发器和索引,pg_ivm可在基表更新时高效维护物化视图,适用于频繁查询但更新较少的场景。该模块为物化视图提供了更灵活和高效的维护方式。

PostgreSQL

pg_ivm

pg_ivm模块为PostgreSQL提供增量视图维护(IVM)功能。 该扩展与PostgreSQL 13、14、15、16和17版本兼容。

描述

**增量视图维护(IVM)**是一种使物化视图保持最新的方法,它只计算并应用视图的增量变化,而不像REFRESH MATERIALIZED VIEW那样从头重新计算内容。当视图只有小部分发生变化时,IVM比重新计算更有效地更新物化视图。

关于视图维护的时机,有两种方法:即时维护和延迟维护。在即时维护中,视图在其基表被修改的同一事务中更新。在延迟维护中,视图在事务提交后更新,例如,在访问视图时,响应用户命令如REFRESH MATERIALIZED VIEW,或定期在后台更新等。pg_ivm提供了一种即时维护方式,即当基表被修改时,物化视图立即在AFTER触发器中更新。

我们将支持IVM的物化视图称为增量可维护物化视图(IMMV)。要创建IMMV,你需要使用关系名称和视图定义查询调用create_immv函数。例如:

SELECT create_immv('myview', 'SELECT * FROM mytab');

这将创建一个名为'myview'的IMMV,定义为SELECT * FROM mytab。这相当于以下创建普通物化视图的命令:

CREATE MATERIALIZED VIEW myview AS SELECT * FROM mytab;

当创建IMMV时,会自动创建一些触发器,以便在其基表被修改时立即更新视图的内容。

postgres=# SELECT create_immv('m', 'SELECT * FROM t0'); 注意:无法自动在immv "m"上创建索引 详细信息:此目标列表没有包含所有主键列,或此视图不包含DISTINCT子句。 提示:在immv上创建索引以实现高效的增量维护。 create_immv ------------- 3 (1) postgres=# SELECT * FROM m; i --- 1 2 3 (3) postgres=# INSERT INTO t0 VALUES (4); INSERT 0 1 postgres=# SELECT * FROM m; -- 自动更新 i --- 1 2 3 4 (4)

请注意,如果你使用PostgreSQL 17或更高版本,在IMMV的自动维护期间,search_path会暂时更改为pg_catalog, pg_temp

安装

要安装pg_ivm,请在模块目录中执行以下命令:

make install

如果您是通过rpm或deb安装的PostgreSQL,则需要开发包(例如,postgresql14-devel或postgresql-server-dev-14)。

重要提示: 如果您想在非默认或自定义构建的PostgreSQL上使用pg_ivm,请不要忘记设置PG_CONFIG变量(make PG_CONFIG=...)或将pg_config命令的路径添加到PATH中。更多信息请参阅这里。 然后,执行CREATE EXTENSION命令。

CREATE EXTENSION pg_ivm;

RPM包和yum仓库

pg_ivm的RPM包可以从PostgreSQL yum仓库获取。详细信息请参阅说明。请注意,我们不是该yum仓库的维护者,其中的pg_ivm RPM包可能并非总是最新版本。

对象

当安装了pg_ivm后,将创建以下对象。

函数

create_immv

使用create_immv函数创建IMMV。

create_immv(immv_name text, view_definition text) RETURNS bigint

create_immv定义一个新的查询IMMV。它会创建一个名为immv_name的表,执行由view_definition指定的查询,并用结果填充IMMV。该查询会被存储在pg_ivm_immv中,以便之后进行增量视图维护时刷新。create_immv返回创建的IMMV中的行数。

创建IMMV时,系统会自动创建一些触发器,以便在基表被修改时立即更新视图内容。此外,如果可能的话,还会自动为IMMV创建一个唯一索引。如果视图定义查询有GROUP BY子句,则会在GROUP BY表达式的列上创建唯一索引。如果视图有DISTINCT子句,则会在目标列表的所有列上创建唯一索引。否则,如果IMMV的目标列表中包含其基表的所有主键属性,则会在这些属性上创建唯一索引。在其他情况下,不会创建索引。

注意,如果你使用PostgreSQL 17或更高版本,在create_immv运行期间,search_path会临时更改为pg_catalog, pg_temp

refresh_imm

使用refresh_immv函数刷新IMMV。

refresh_immv(immv_name text, with_data bool) RETURNS bigint

refresh_immv完全替换IMMV的内容,就像REFRESH MATERIALIZED VIEW命令对物化视图所做的那样。要执行此函数,你必须是IMMV的所有者(在PostgreSQL 16或更早版本中)或对IMMV拥有MAINTAIN权限(在PostgreSQL 17或更高版本中)。旧内容将被丢弃。

with_data标志对应于REFRESH MATERIALIZED VIEW命令的WITH [NO] DATA选项。如果with_data为true,将执行后台查询以提供新数据,如果IMMV未填充,则创建用于维护视图的触发器。此外,如果可能且视图尚未拥有,还会为IMMV创建唯一索引。如果with_data为false,则不会生成新数据,IMMV将变为未填充状态,并且会从IMMV中删除触发器。注意,未填充的IMMV仍然可以扫描,尽管结果为空。这种行为在将来可能会改变,当扫描未填充的IMMV时可能会引发错误。

注意,如果你使用PostgreSQL 17或更高版本,在refresh_immv运行期间,search_path会临时更改为pg_catalog, pg_temp

get_immv_def

get_immv_def重构IMMV的底层SELECT命令。(这是一个反编译重构,而不是命令的原始文本。)

get_immv_def(immv regclass) RETURNS text

IMMV元数据目录

目录pg_ivm_immv存储IMMV信息。

名称类型描述
immvrelidregclassIMMV的OID
viewdeftext视图定义的查询树(以nodeToString()表示形式)
ispopulatedbool如果IMMV当前已填充则为True

示例

总的来说,IMMV允许比REFRESH MATERIALIZED VIEW更快的更新,但代价是对其基表的更新速度较慢。基表更新较慢是因为需要触发触发器,并且IMMV在每个修改语句的触发器中更新。

例如,假设有一个如下定义的普通物化视图:

test=# CREATE MATERIALIZED VIEW mv_normal AS SELECT a.aid, b.bid, a.abalance, b.bbalance FROM pgbench_accounts a JOIN pgbench_branches b USING(bid); SELECT 10000000

更新这个物化视图的基表中的一个元组很快,但对这个视图执行REFRESH MATERIALIZED VIEW命令需要很长时间:

test=# UPDATE pgbench_accounts SET abalance = 1000 WHERE aid = 1; UPDATE 1 Time: 9.052 ms test=# REFRESH MATERIALIZED VIEW mv_normal ; REFRESH MATERIALIZED VIEW Time: 20575.721 ms (00:20.576)

另一方面,使用相同的视图定义创建IMMV后:

test=# SELECT create_immv('immv',
'SELECT a.aid, b.bid, a.abalance, b.bbalance
FROM pgbench_accounts a JOIN pgbench_branches b USING(bid)');
NOTICE:  created index "immv_index" on immv "immv"
create_immv
-------------
10000000
(1 row)

更新基表中的一个元组比普通视图需要更多时间,但其内容会自动更新,这比REFRESH MATERIALIZED VIEW命令更快。

test=# UPDATE pgbench_accounts SET abalance = 1234 WHERE aid = 1; UPDATE 1 Time: 15.448 ms test=# SELECT * FROM immv WHERE aid = 1; aid | bid | abalance | bbalance -----+-----+----------+---------- 1 | 1 | 1234 | 0 (1 row)

IMMV上的适当索引对于高效的IVM是必要的,因为我们需要在IMMV中查找要更新的元组。如果没有索引,将会花费很长时间。

因此,当通过create_immv函数创建IMMV时,如果可能,会自动在其上创建唯一索引。如果视图定义查询有GROUP BY子句,会在GROUP BY表达式的列上创建唯一索引。此外,如果视图有DISTINCT子句,会在目标列表中的所有列上创建唯一索引。否则,如果IMMV在目标列表中包含其所有基表的主键属性,会在这些属性上创建唯一索引。在其他情况下,不会创建索引。

在前面的例子中,在"immv"的aid和bid列上创建了一个名为"immv_index"的唯一索引,这使得视图的快速更新成为可能。删除这个索引会使更新视图花费更长的时间。

test=# DROP INDEX immv_index; DROP INDEX test=# UPDATE pgbench_accounts SET abalance = 9876 WHERE aid = 1; UPDATE 1 Time: 3224.741 ms (00:03.225)

支持的视图定义和限制

目前,IMMV的视图定义可以包含内连接、DISTINCT子句、一些内置聚合函数、FROM子句中的简单子查询、EXISTS子查询和简单的CTE(WITH查询)。支持包括自连接在内的内连接,但不支持外连接。支持的聚合函数有count、sum、avg、min和max。其他聚合函数、包含聚合或DISTINCT子句的子查询、FROM子句以外的子查询、窗口函数、HAVINGORDER BYLIMIT/OFFSETUNION/INTERSECT/EXCEPTDISTINCT ONTABLESAMPLEVALUES以及FOR UPDATE/SHARE不能在视图定义中使用。

基表必须是简单表。不能使用视图、物化视图、继承父表、分区表、分区和外部表。

视图定义查询中不能包含任何系统列。

目标列表不能包含以__ivm_开头的列名。

视图目标列表中使用的数据类型必须具有btree访问方法的默认运算符类。例如,jsonxmlpoint类型不能出现在目标列表中。

不支持逻辑复制,也就是说,即使发布节点上的基表被修改,订阅节点上基于这些基表定义的IMMV也不会更新。

注意事项

聚合函数

支持的聚合函数包括countsumavgminmax。目前仅支持内置聚合函数,不能使用用户自定义聚合。

当创建包含聚合的IMMV时,一些以__ivm开头的额外列会自动添加到目标列表中。__ivm_count__包含每个分组中聚合的元组数。此外,还会为每个聚合值列添加多个额外列以维护其值。例如,为维护平均值会添加名为__ivm_count_avg____ivm_sum_avg__的列。当基表被修改时,新的聚合值会使用旧的聚合值和存储在IMMV中相关额外列的值进行增量计算。

注意,对于minmax,当包含当前最小或最大值的元组从基表中删除时,可能需要从基表重新计算受影响分组的新值。因此,更新包含这些函数的IMMV可能需要较长时间。

另外,在IMMV中对realfloat4)类型或double precisionfloat8)类型使用sumavg是不安全的,因为由于这些类型的精度有限,IMMV中的聚合值可能与从基表计算的结果不同。为避免此问题,请使用numeric类型。

聚合的限制

如果有GROUP BY子句,GROUP BY中指定的表达式必须出现在目标列表中。这是用于识别IMMV中需要更新的元组的方式。这些属性用作搜索IMMV中元组的扫描键,因此需要在它们上建立索引以实现高效的IVM。

目标列表不能包含含有聚合的表达式。

子查询

支持FROM子句中的简单子查询和WHERE子句中的EXISTS子查询。

子查询的限制

支持使用EXISTS的子查询和FROM子句中的简单子查询。不支持除'AND'以外条件的EXISTS子查询和目标列表中的子查询。EXISTS子查询仅支持在WHERE中使用,不支持在目标列表中使用。

如果EXISTS包含引用外部查询表中列的列,这些列必须包含在目标列表中。

不支持包含聚合函数或DISTINCT的子查询。

CTE

支持简单的CTE(WITH查询)。

CTE的限制

不支持包含聚合函数或DISTINCTWITH查询。

不允许递归查询(WITH RECURSIVE)。也不允许未引用的CTE,即CTE必须在视图定义查询中至少被引用一次。

DISTINCT

IMMV的定义查询中允许使用DISTINCT。假设在包含重复元组的基表上定义了带DISTINCT的IMMV。当从基表删除元组时,只有当元组的重复数变为零时,视图中的元组才会被删除。此外,当向基表插入元组时,只有当视图中不存在相同的元组时,才会向视图中插入元组。

从物理上讲,使用DISTINCT定义的IMMV包含消除重复后的元组,每个元组的重复数存储在创建此类IMMV时添加的名为__ivm_count__的额外列中。

TRUNCATE

当基表被截断时,如果视图定义查询不包含没有GROUP BY子句的聚合,IMMV也会被截断,内容变为空。没有GROUP BY子句的聚合视图始终有一行。因此,在这种情况下,如果基表被截断,IMMV只会被刷新而不是被截断。

并发事务

假设一个IMMV定义在两个基表上,每个表在不同的并发事务中同时被修改。在先提交的事务中,IMMV可以只考虑该事务中发生的变化进行更新。另一方面,为了在后提交的事务中正确更新IMMV,我们需要知道两个事务中发生的变化。因此,在READ COMMITTED模式下,一旦基表被修改,就会立即在IMMV上持有ExclusiveLock,以确保IMMV在后一个事务中在前一个事务提交后更新。在REPEATABLE READSERIALIZABLE模式下,如果锁获取失败,会立即引发错误,因为在这些模式下其他事务中发生的任何变化都不可见,在这种情况下IMMV无法正确更新。但是,作为例外,如果IMMV只有一个基表且不使用DISTINCT或GROUP BY,并且表通过INSERT修改,那么在IMMV上持有的锁是RowExclusiveLock

行级安全性

如果某些基表有行级安全策略,对物化视图所有者不可见的行将从结果中排除。此外,在视图增量维护时,这些行也会被排除。然而,如果在创建物化视图后定义了新策略或更改了策略,新策略不会应用于视图内容。要应用新策略,需要重新创建IMMV。

如何禁用或启用即时维护

当我们希望保持IMMV最新,且基表的小部分不频繁修改时,IVM是有效的。由于即时维护的开销,当基表频繁修改时IVM不太有效。此外,当修改基表的大部分或向基表插入大量数据时,IVM不太有效,维护成本可能大于从头刷新。

在这种情况下,我们可以在修改基表之前使用refesh_immv函数,并将with_data设为false来禁用即时维护。修改基表后,调用refresh_immv并将with_data设为true来刷新视图数据并启用即时维护。

作者

IVM 开发团队

许可证

PostgreSQL 许可证

版权声明

  • 部分版权所有 © 1996-2022,PostgreSQL 全球开发组
  • 部分版权所有 © 2022,IVM 开发组

编辑推荐精选

Vora

Vora

免费创建高清无水印Sora视频

Vora是一个免费创建高清无水印Sora视频的AI工具

Refly.AI

Refly.AI

最适合小白的AI自动化工作流平台

无需编码,轻松生成可复用、可变现的AI自动化工作流

酷表ChatExcel

酷表ChatExcel

大模型驱动的Excel数据处理工具

基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。

AI工具酷表ChatExcelAI智能客服AI营销产品使用教程
TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
AIWritePaper论文写作

AIWritePaper论文写作

AI论文写作指导平台

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

AI辅助写作AI工具AI论文工具论文写作智能生成大纲数据安全AI助手热门
博思AIPPT

博思AIPPT

AI一键生成PPT,就用博思AIPPT!

博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。

AI办公办公工具AI工具博思AIPPTAI生成PPT智能排版海量精品模板AI创作热门
潮际好麦

潮际好麦

AI赋能电商视觉革命,一站式智能商拍平台

潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。

iTerms

iTerms

企业专属的AI法律顾问

iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。

SimilarWeb流量提升

SimilarWeb流量提升

稳定高效的流量提升解决方案,助力品牌曝光

稳定高效的流量提升解决方案,助力品牌曝光

Sora2视频免费生成

Sora2视频免费生成

最新版Sora2模型免费使用,一键生成无水印视频

最新版Sora2模型免费使用,一键生成无水印视频

下拉加载更多