单纯用普通视图撑不起实时看板,因其仅为查询快照;真要实时需依赖实时物化视图、流式SQL引擎或手动增量聚合表,如AnalyticDB PostgreSQL版支持的实时物化视图可在基表变更后自动刷新,但需显式启用增量维护且受主键、有序写入等条件约束。

单纯用普通视图(CREATE VIEW)撑不起实时看板——它只是查询快照,不随底层数据变化自动更新。真要“实时”,得靠能响应变更的机制,比如实时物化视图、流式SQL引擎或带增量逻辑的手动聚合表。
实时物化视图:自动刷新但有前提
像 AnalyticDB PostgreSQL 版、Oracle 或部分新版 PostgreSQL(配合 pg_cron + 触发器)支持的「实时物化视图」,能在基表 INSERT/UPDATE/DELETE 后自动触发刷新。但它不是魔法:
- 必须显式声明为「实时」或启用增量维护能力,普通
CREATE MATERIALIZED VIEW默认是静态快照,需手动REFRESH MATERIALIZED VIEW - 依赖数据库是否支持 changelog 捕获;若基表没主键或无序写入,增量合并可能出错
- 高并发写入时,刷新延迟可能达秒级,不是严格事件驱动——适合 TPS
- 不能嵌套太深:A → B → C 三级实时物化视图链路,在 AnalyticDB 中可行,但在原生 PostgreSQL 中会退化为全量刷新
Flink SQL 流式视图:把 Kafka 当表用
当数据源是 Kafka 或 Pulsar,Flink SQL 的 CREATE TABLE 本质就是定义一张持续流入的「流式表」,再用 CREATE VIEW 基于它做逻辑封装:
-
CREATE TABLE orders_stream (... ) WITH ('connector' = 'kafka', ...)是起点,不是传统意义的存储表 -
CREATE VIEW hourly_sales AS SELECT DATE_TRUNC('HOUR', order_time) AS hour, COUNT(*) FROM orders_stream GROUP BY DATE_TRUNC('HOUR', order_time)这个 view 会持续输出 changelog 流(+I, -U, +U),下游可接 JDBC 写入 MySQL 或直接查 Flink 的SELECT * FROM hourly_sales结果表 - 注意窗口函数必须带时间属性:
order_time字段需声明为ROWTIME或PROCTIME,否则TUMBLING窗口无法触发 - 别在 view 里写
LIMIT——流式查询不支持,会报UnsupportedOperationException
手动增量聚合表:可控但需自己兜底
在 MySQL / PostgreSQL 上跑定时任务聚合,是最易落地也最容易翻车的方式:
- 用
INSERT ... ON CONFLICT DO UPDATE(PostgreSQL)或INSERT ... ON DUPLICATE KEY UPDATE(MySQL)保证幂等,避免重复累加 - 过滤条件必须跳过最新 N 分钟数据,例如
WHERE created_at > last_max_ts AND created_at ,防事务未提交导致数据丢失 - 每次任务执行前先查
MAX(created_at)记录到元数据表,而不是依赖固定时间间隔——否则上游延迟会导致漏数据 - 字段设计要预留扩展性:比如汇总表里存
hour_start而非hour,方便后续切到 15 分钟粒度
真正难的不是写一条 SQL,而是判断哪条路径能扛住凌晨三点的订单洪峰,同时让运营同学刷看板时不看到跳变数字。选型时盯着三件事:数据源是否有序、下游能否消费 changelog、DBA 是否允许开实时物化视图权限——其余都是细节补丁。

















