Skip to content

KingBaseES 物化视图

物化视图概述

物化视图是一种特殊的数据库对象,它将查询结果存储为物理表,定期或手动刷新,以提供快速的数据访问。与普通视图相比,物化视图可以显著提高复杂查询的性能,特别是在大数据量和复杂查询场景下。

物化视图与普通视图的区别

特性普通视图物化视图
存储方式只存储查询定义,不存储数据存储查询结果数据
查询性能查询时动态执行,性能取决于查询复杂度直接读取预计算结果,性能高
数据新鲜度总是返回最新数据数据可能过时,需要定期刷新
存储空间几乎不占用存储空间占用存储空间存储数据
维护成本无维护成本需要定期刷新,有维护成本
适用场景简单查询,需要最新数据复杂查询,数据更新不频繁

物化视图的适用场景

  1. 复杂查询优化:对复杂的查询(如多表关联、聚合计算、分析函数等)创建物化视图,提高查询性能。
  2. 数据仓库和数据分析:在数据仓库环境中,为常用的分析查询创建物化视图,加速报表生成。
  3. 只读数据访问:对只读或读写比较低的数据创建物化视图,提高读取性能。
  4. 跨数据库查询:对跨数据库的查询创建物化视图,减少跨数据库访问的开销。
  5. 历史数据查询:对历史数据创建物化视图,加速历史数据的查询。

物化视图的创建与管理

创建物化视图

基本语法

sql
CREATE MATERIALIZED VIEW [IF NOT EXISTS] view_name
    [ (column_name [, ...] ) ]
    [ WITH ( storage_parameter [= value] [, ... ] ) ]
    AS query
    [ WITH [ NO ] DATA ];

创建示例

sql
-- 创建基本物化视图
CREATE MATERIALIZED VIEW mv_sales_summary AS
SELECT 
    product_id,
    SUM(quantity) AS total_quantity,
    SUM(amount) AS total_amount,
    COUNT(*) AS order_count,
    EXTRACT(MONTH FROM sale_date) AS sale_month,
    EXTRACT(YEAR FROM sale_date) AS sale_year
FROM 
    sales
GROUP BY 
    product_id, EXTRACT(YEAR FROM sale_date), EXTRACT(MONTH FROM sale_date);

-- 创建带有索引的物化视图
CREATE MATERIALIZED VIEW mv_sales_by_region AS
SELECT 
    region,
    product_id,
    SUM(quantity) AS total_quantity,
    SUM(amount) AS total_amount
FROM 
    sales s
JOIN 
    customers c ON s.customer_id = c.customer_id
GROUP BY 
    region, product_id;

-- 为物化视图创建索引
CREATE INDEX idx_mv_sales_by_region ON mv_sales_by_region(region, product_id);

-- 创建不包含数据的物化视图
CREATE MATERIALIZED VIEW mv_sales_pending WITH NO DATA AS
SELECT 
    *
FROM 
    sales
WHERE 
    status = 'pending';

刷新物化视图

物化视图的刷新是指将物化视图的数据更新为最新的查询结果。KingBaseES 支持多种刷新方式:

1. 完全刷新(Complete Refresh)

完全刷新会删除物化视图中的所有数据,然后重新执行查询生成新的数据。

sql
-- 完全刷新物化视图
REFRESH MATERIALIZED VIEW mv_sales_summary;

-- 完全刷新物化视图,不锁定数据(KingBaseES V8R3+支持)
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_sales_summary;

2. 增量刷新(Incremental Refresh)

增量刷新只更新物化视图中发生变化的数据,而不是重新生成所有数据。增量刷新需要物化视图有一个唯一索引,并且查询支持增量更新。

sql
-- 增量刷新物化视图
REFRESH MATERIALIZED VIEW mv_sales_summary WITH DATA;

-- 增量刷新物化视图,使用唯一索引
CREATE UNIQUE INDEX idx_mv_sales_summary ON mv_sales_summary(product_id, sale_year, sale_month);
REFRESH MATERIALIZED VIEW mv_sales_summary WITH INCREMENTAL;

3. 自动刷新

可以通过触发器或定时任务实现物化视图的自动刷新。

使用触发器刷新
sql
-- 创建触发器函数
CREATE OR REPLACE FUNCTION refresh_mv_sales_summary()
RETURNS TRIGGER AS $$
BEGIN
    REFRESH MATERIALIZED VIEW CONCURRENTLY mv_sales_summary;
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- 创建触发器
CREATE TRIGGER trg_refresh_mv_sales_summary
AFTER INSERT OR UPDATE OR DELETE ON sales
FOR EACH STATEMENT
EXECUTE FUNCTION refresh_mv_sales_summary();
使用定时任务刷新

可以使用 KingBaseES 的定时任务功能(如 pg_cron 扩展)定期刷新物化视图。

sql
-- 安装 pg_cron 扩展
CREATE EXTENSION IF NOT EXISTS pg_cron;

-- 设置定时任务,每天凌晨 2 点刷新物化视图
SELECT cron.schedule('0 2 * * *', 'REFRESH MATERIALIZED VIEW CONCURRENTLY mv_sales_summary');

-- 查看定时任务
SELECT * FROM cron.job;

管理物化视图

查看物化视图

sql
-- 查看所有物化视图
SELECT 
    oid, 
    relname AS view_name, 
    relowner::regrole AS owner, 
    relnamespace::regnamespace AS schema_name,
    reloptions AS storage_options
FROM 
    sys_class
WHERE 
    relkind = 'm';

-- 查看物化视图的定义
SELECT 
    viewname AS view_name,
    definition
FROM 
    sys_matviews
WHERE 
    viewname = 'mv_sales_summary';

-- 查看物化视图的状态
SELECT 
    oid,
    relname AS view_name,
    last_refresh
FROM 
    sys_matviews;

修改物化视图

sql
-- 修改物化视图的存储参数
ALTER MATERIALIZED VIEW mv_sales_summary
    SET (fillfactor = 70, autovacuum_enabled = true);

-- 重命名物化视图
ALTER MATERIALIZED VIEW mv_sales_summary RENAME TO mv_sales_summary_old;

-- 修改物化视图的所有者
ALTER MATERIALIZED VIEW mv_sales_summary OWNER TO new_owner;

-- 添加注释
COMMENT ON MATERIALIZED VIEW mv_sales_summary IS '销售汇总物化视图';

删除物化视图

sql
-- 删除物化视图
DROP MATERIALIZED VIEW IF EXISTS mv_sales_summary;

-- 删除物化视图及其依赖对象
DROP MATERIALIZED VIEW IF EXISTS mv_sales_summary CASCADE;

重命名物化视图

sql
-- 重命名物化视图
ALTER MATERIALIZED VIEW mv_sales_summary RENAME TO mv_sales_summary_new;

物化视图的优化

1. 选择合适的刷新策略

根据业务需求和数据更新频率选择合适的刷新策略:

  • 完全刷新:适用于数据更新不频繁、物化视图较小的场景。
  • 增量刷新:适用于数据更新频繁、物化视图较大的场景。
  • 并发刷新:适用于需要持续访问物化视图的场景,刷新时不阻塞查询。
  • 定时刷新:适用于对数据新鲜度要求不高的场景。

2. 创建合适的索引

为物化视图创建合适的索引可以显著提高查询性能:

sql
-- 为物化视图创建主键索引
ALTER MATERIALIZED VIEW mv_sales_summary ADD PRIMARY KEY (product_id, sale_year, sale_month);

-- 为常用查询列创建索引
CREATE INDEX idx_mv_sales_summary_product ON mv_sales_summary(product_id);
CREATE INDEX idx_mv_sales_summary_date ON mv_sales_summary(sale_year, sale_month);

3. 优化物化视图查询

物化视图的查询性能取决于其定义的查询复杂度和数据量。优化物化视图查询的方法:

  • 简化查询逻辑:避免在物化视图中使用过于复杂的查询。
  • 限制数据量:使用 WHERE 子句限制物化视图的数据量。
  • 合理分组:根据查询需求合理设计分组和聚合方式。
  • 避免过度连接:尽量减少物化视图中的表连接数量。

4. 监控物化视图性能

定期监控物化视图的性能,包括刷新时间、查询性能和存储空间使用情况:

sql
-- 监控物化视图的刷新时间
SELECT 
    viewname AS view_name,
    last_refresh,
    pg_size_pretty(pg_total_relation_size(viewname)) AS size
FROM 
    sys_matviews;

-- 监控物化视图的查询性能
SELECT 
    relname AS view_name,
    idx_scan AS index_scans,
    seq_scan AS sequential_scans,
    idx_tup_read AS index_tuples_read,
    idx_tup_fetch AS index_tuples_fetched,
    n_tup_ins AS tuples_inserted,
    n_tup_upd AS tuples_updated,
    n_tup_del AS tuples_deleted
FROM 
    sys_stat_user_tables
WHERE 
    relname LIKE 'mv_%';

物化视图的高级特性

1. 分区物化视图

KingBaseES 支持创建分区物化视图,将物化视图的数据按照一定的规则分区存储,提高查询和维护性能。

sql
-- 创建分区物化视图
CREATE MATERIALIZED VIEW mv_sales_partitioned
PARTITION BY RANGE (sale_date)
AS
SELECT 
    *
FROM 
    sales
ORDER BY 
    sale_date;

-- 创建分区
CREATE MATERIALIZED VIEW PARTITION mv_sales_2023 PARTITION OF mv_sales_partitioned
    FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');

CREATE MATERIALIZED VIEW PARTITION mv_sales_2024 PARTITION OF mv_sales_partitioned
    FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');

2. 物化视图日志

物化视图日志用于支持物化视图的增量刷新,记录基表的变化信息。

sql
-- 创建物化视图日志
CREATE MATERIALIZED VIEW LOG ON sales
    WITH (primary key, rowid) 
    INCLUDING NEW VALUES;

-- 查看物化视图日志
SELECT * FROM mlog$_sales;

3. 嵌套物化视图

嵌套物化视图是指基于其他物化视图创建的物化视图,可以用于构建复杂的数据分析模型。

sql
-- 创建基础物化视图
CREATE MATERIALIZED VIEW mv_sales_daily AS
SELECT 
    product_id,
    sale_date,
    SUM(quantity) AS daily_quantity,
    SUM(amount) AS daily_amount
FROM 
    sales
GROUP BY 
    product_id, sale_date;

-- 创建嵌套物化视图
CREATE MATERIALIZED VIEW mv_sales_monthly AS
SELECT 
    product_id,
    EXTRACT(MONTH FROM sale_date) AS sale_month,
    EXTRACT(YEAR FROM sale_date) AS sale_year,
    SUM(daily_quantity) AS monthly_quantity,
    SUM(daily_amount) AS monthly_amount
FROM 
    mv_sales_daily
GROUP BY 
    product_id, EXTRACT(YEAR FROM sale_date), EXTRACT(MONTH FROM sale_date);

物化视图的版本差异

V8 与 V7 版本的差异

  1. 物化视图支持

    • V7 版本基本支持物化视图,但功能有限。
    • V8 版本增强了物化视图的功能,支持并发刷新和增量刷新。
  2. 刷新策略

    • V7 版本只支持完全刷新。
    • V8 版本支持完全刷新、并发刷新和增量刷新。
  3. 性能优化

    • V8 版本优化了物化视图的刷新性能,减少了刷新时间。
    • V8 版本支持物化视图的并行刷新,提高了刷新效率。

V8R3 与 V8R2 版本的差异

  1. 并发刷新

    • V8R3 版本支持物化视图的并发刷新,刷新时不阻塞查询。
    • V8R2 版本刷新物化视图时会阻塞查询。
  2. 增量刷新增强

    • V8R3 版本增强了增量刷新的功能,支持更多类型的查询。
    • V8R3 版本优化了增量刷新的性能,减少了增量刷新的时间。
  3. 新特性

    • V8R3 版本支持分区物化视图,提高了大物化视图的管理和查询性能。
    • V8R3 版本支持物化视图的自动刷新,通过定时任务实现。

常见问题(FAQ)

如何选择物化视图的刷新方式?

  1. 完全刷新:适用于数据量小、更新频率低的物化视图。
  2. 并发刷新:适用于需要持续访问的物化视图,刷新时不阻塞查询。
  3. 增量刷新:适用于数据量、更新频率高的物化视图,只更新变化的数据。
  4. 自动刷新:适用于对数据新鲜度要求高的物化视图,通过触发器或定时任务自动刷新。

如何优化物化视图的刷新性能?

  1. 使用增量刷新:对于大物化视图,使用增量刷新可以显著减少刷新时间。
  2. 使用并发刷新:对于需要持续访问的物化视图,使用并发刷新可以避免阻塞查询。
  3. 优化基表索引:为基表创建合适的索引,提高物化视图刷新时的查询性能。
  4. 选择合适的刷新时间:在系统负载低的时间段刷新物化视图,减少对系统的影响。
  5. 使用并行刷新:对于大物化视图,启用并行刷新可以提高刷新效率。

物化视图占用大量存储空间怎么办?

  1. 限制数据量:在物化视图查询中使用 WHERE 子句限制数据量。
  2. 定期清理旧数据:创建分区物化视图,定期删除或归档旧分区。
  3. 压缩物化视图:启用物化视图的压缩功能,减少存储空间占用。
  4. 使用增量刷新:减少物化视图的全量刷新次数,降低存储空间的临时占用。

如何监控物化视图的刷新状态?

sql
-- 查看物化视图的刷新状态
SELECT 
    viewname AS view_name,
    last_refresh,
    pg_size_pretty(pg_total_relation_size(viewname)) AS size
FROM 
    sys_matviews;

-- 查看物化视图的刷新历史(如果有审计日志)
SELECT 
    *
FROM 
    sys_audit_log
WHERE 
    object_name = 'mv_sales_summary' AND action = 'REFRESH';

物化视图可以用于实时数据查询吗?

物化视图不适合实时数据查询,因为它的数据需要定期或手动刷新,存在一定的延迟。对于实时数据查询,建议使用普通视图或直接查询基表。

总结

物化视图是 KingBaseES 中用于提高复杂查询性能的重要技术,可以显著减少查询时间,提高系统响应速度。DBA 需要根据业务需求和数据特点,合理设计和管理物化视图,选择合适的刷新策略和优化方法。

在实际生产环境中,DBA 需要:

  1. 理解物化视图的特点和适用场景
  2. 合理设计物化视图的查询和刷新策略
  3. 为物化视图创建合适的索引
  4. 定期监控物化视图的性能和存储空间使用情况
  5. 根据业务需求调整物化视图的设计和刷新策略
  6. 利用物化视图的高级特性,如分区物化视图和嵌套物化视图,提高系统的整体性能

通过合理使用物化视图,可以提高 KingBaseES 数据库的查询性能,减少系统负载,提升用户体验。