自动使用物化视图进行查询优化(引入自 v1.5.0 版本)
自 v1.5.0 版本起,Cloudberry Database 支持在查询规划阶段自动使用物化视图来计算部分或全部查询(即 AQUMV)。这一功能特别适用于在大表上进行的查询,能显著提高查询处理时间。AQUMV 使用增量物化视图 (IMV),因为当相关表有写入操作时,IMV 通常能保持最新的数据。
场景说明
- 大数据量的聚合查询:对于需要从数百万条记录中进行聚合的查询,AQUMV 能显著减少查询时间。
- 频繁更新的大表:在数据频繁更新的环境中,使用 IMV 可以确保查询结果的实时性和准确性。
- 复杂计算的场景:对于包含复杂计算(如以下示例中的平方根和绝对值计算)的查询,AQUMV 可以通过预计算这些值在物化视图中,加快查询速度。
使用示例
要启用 AQUMV 功能,需要先创建物化视图,并将系统参数 enable_answer_query_using_materialized_views
的值设为 ON
。下面是不使用 AQUMV 与使用 AQUMV 执行相同复杂查询的结果对比。
-
关闭 GPORCA 执行优化器,使用基于 Postgres 的执行优化器。
SET optimizer TO off;
-
创建表格
aqumv_t1
。CREATE TABLE aqumv_t1(c1 INT, c2 INT, c3 INT) DISTRIBUTED BY (c1);
-
往表中插入数据,并收集表上的统计信息。
INSERT INTO aqumv_t1 SELECT i, i+1, i+2 FROM generate_series(1, 100000000) i;
ANALYZE aqumv_t1; -
在不开启 AQUMV 的情况下执行查询,耗时 7384.329 ms。
SELECT SQRT(ABS(ABS(c2) - c1 - 1) + ABS(c2)) FROM aqumv_t1 WHERE c1 > 30 AND c1 < 40 AND SQRT(ABS(c2)) > 5.8;
sqrt
-------------------66.0827625302982196.2449979983983985.9160797830996166.1644140029689766.3245553203367595.830951894845301
(7 rows)
Time: 7384.329 ms (00:07.384)该查询的计划如下,可见优化器对表进行了扫描 (
Seq Scan on aqumv_t1
)。EXPLAIN(COSTS OFF) SELECT SQRT(ABS(ABS(c2) - c1 - 1) + ABS(c2)) FROM aqumv_t1 WHERE c1 > 30 AND c1 < 40 AND SQRT(ABS(c2)) > 5.8;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
-> Seq Scan on aqumv_t1
Filter: ((c1 > 30) AND (c1 < 40) AND (sqrt((abs(c2))::double precision) > '5.8'::double pre
cision))
Optimizer: Postgres query optimizer
(4 rows) -
现在基于
aqumv_t1
创建物化视图mvt1
,并收集该视图的统计信息。CREATE INCREMENTAL MATERIALIZED VIEW mvt1 AS SELECT c1 AS mc1, c2 AS mc2, ABS(c2) AS mc3, ABS(ABS(c2) - c1 - 1) AS mc4
FROM aqumv_t1 WHERE c1 > 30 AND c1 < 40;
ANALYZE mvt1; -
开启 AQUMV 相关配置参数:
SET enable_answer_query_using_materialized_views = ON;
-
现在 AQUMV 已开启,再次执行相同的表查询,耗时 45.701 ms。
SELECT SQRT(ABS(ABS(c2) - c1 - 1) + ABS(c2)) FROM aqumv_t1 WHERE c1 > 30 AND c1 < 40 AND SQRT(ABS(c2)) > 5.8;
sqrt
-------------------66.0827625302982196.2449979983983985.8309518948453015.9160797830996166.1644140029689766.324555320336759
(7 rows)
Time: 45.701 ms该查询的计划如下,可见优化器没有扫描
aqumv_t1
表,而扫描了物化视图mvt1
(Seq Scan on public.mvt1
)。explain(verbose, costs off)select sqrt(abs(abs(c2) - c1 - 1) + abs(c2)) from aqumv_t1 where c1 > 30 and c1 < 40 and sqrt(abs(c2)) > 5.8;
QUERY PLAN
--------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Output: (sqrt(((mc4 + mc3))::double precision))
-> Seq Scan on public.mvt1
Output: sqrt(((mc4 + mc3))::double precision)
Filter: (sqrt((mvt1.mc3)::double precision) > '5.8'::double precision)
Settings: enable_answer_query_using_materialized_views = 'on', optimizer = 'off'
Optimizer: Postgres query optimizer
(7 rows)在以上示例中,在没有使用物化视图的情况下,查询耗时为 7384.329 毫秒。而启用 AQUMV 后,使用物化视图的相同查询仅耗时 45.701 毫秒。这说明 物化视图通过预先计算和存储相关计算结果,只包含了满足特定条件(
c1 > 30 and c1 < 40
)的行。因此以上表查询
select sqrt(abs(abs(c2) - c1 - 1) + abs(c2)) from aqumv_t1 where c1 > 30 and c1 < 40 and sqrt(abs(c2)) > 5.8;
实际上等效于对物化视图的查询语句select sqrt(mc4 + mc3) from mvt1 where sqrt(mc3) > 5.8;
。
通过这种方式,当执行相同的查询时,可以直接从物化视图中获取数据,而不是从原始表中,这样 AQUMV 能显著提高查询性能,特别是在处理大数据量和复杂计算时。
实现原理
AQUMV 是通过对查询树进行等效转换来实现查询优化的。
表查询只有满足以下条件后,Cloudberry Database 才会自动使用物化视图:
- 物化视图必须包含查询表达式所需的所有行。
- 如果物化视图包含比查询更多的行,可能需要添加额外的过滤条件。
- 所有输出表达式必须能够从视图的输出中计算得出。
- 输出表达式可以完全或部分与物化视图的目标列表匹配。
当存在多个有效的物化视图候选项时,或者当从物化视图中查询的成本高于直接从原始表中查询(例如,原始表有索引等情况),可以让规划器根据代价估算决定最佳选择。
使用限制
- 只支持对单一关系的
SELECT
查询,适用于物化视图查询和原始查询。 - 当前不支持的功能包括:聚合 (AGG)、子查询、原始查询的 排序 (ORDER BY)、连接 (JOIN)、子链接(SUBLINK)、分组 (GROUP BY)、窗口函数、公共表表达式 (CTE)、去重 (DISTINCT ON)、刷新物化视图(REFRESH MATERIALIZED VIEW)、
CREATE AS
语句。