oracle 23c 不支持基于纯json列创建可快速刷新的物化视图,因其物化视图日志无法捕获json内部字段级变更,导致fast刷新失效,只能退化为complete刷新。
直接说结论:oracle 23c 不支持基于纯json列(如 json 类型列)创建可快速刷新(fast)的物化视图,因为物化视图日志(mlog$)无法捕获 json 列内部字段级变更;若强行创建,刷新会失败或退化为全量刷新,失去性能意义。
为什么 JSON 列不能用于 FAST 刷新物化视图
物化视图的 FAST 刷新依赖底层基表的物化视图日志(mlog$),而该日志只记录行级 DML(INSERT/UPDATE/DELETE)及主键/ROWID 变化,**不解析、不追踪 JSON 列内部结构变动**。即使你更新了 JSON 字段中某个键值(例如 UPDATE t SET data = JSON_MODIFY(data, '$.status', 'done') WHERE id = 1),日志里只记下整行被 U(update),但无法告诉物化视图“哪几个 JSON 字段变了”,因此无法增量应用变更。
-
JSON列本身不支持创建物化视图日志(CREATE MATERIALIZED VIEW LOG ON ...会报ORA-12089或隐式拒绝) - 即使基表有主键且定义了
REFRESH FAST,只要 SELECT 中包含JSON_*()函数(如JSON_VALUE、JSON_TABLE),Oracle 就自动禁用 FAST 刷新能力 -
IS JSON约束或FORMAT JSON不改变这一限制——它们只校验合法性,不提供结构变更感知
可行替代方案:用 JSON_TABLE + 关系表做物化视图
如果你需要加速对 JSON 内容的聚合或过滤查询,正确做法是**把 JSON 解构为关系表,再在关系表上建物化视图**:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 先用
JSON_TABLE将常用 JSON 字段投影为物理列(建议存入新表或作为物化视图 AS 子句的一部分) - 确保该关系表有主键,并为其创建物化视图日志:
CREATE MATERIALIZED VIEW LOG ON extracted_table WITH PRIMARY KEY, ROWID; - 在
extracted_table上创建REFRESH FAST ON COMMIT的物化视图,而非直接操作原始 JSON 表 - 若必须保持原始 JSON 表不可变,可将
JSON_TABLE逻辑写进物化视图定义中,但需接受REFRESH COMPLETE—— 这意味着每次刷新都重执行整个JSON_TABLE解析,开销大
CREATE MATERIALIZED VIEW mv_json_summary
BUILD IMMEDIATE
REFRESH COMPLETE ON DEMAND
AS
SELECT jt.id, jt.status, jt.amount, COUNT(*) cnt
FROM json_orders o,
JSON_TABLE(o.payload, '$'
COLUMNS (
id NUMBER PATH '$.id',
status VARCHAR2(20) PATH '$.status',
amount NUMBER PATH '$.amount'
)
) jt
GROUP BY jt.id, jt.status, jt.amount;
ORA-12014 / ORA-12052 错误怎么绕过
常见错误现象:执行 CREATE MATERIALIZED VIEW ... REFRESH FAST ... AS SELECT * FROM t WHERE json_col IS JSON 后报 ORA-12014: table does not contain a primary key 或 ORA-12052: cannot fast refresh materialized view —— 这不是因为你没加主键,而是 Oracle 检测到查询含不可刷新表达式(包括任何 JSON 函数、虚拟列、子查询等)。
- 检查物化视图定义是否含
JSON_VALUE、JSON_QUERY、JSON_EXISTS等函数:全部移除才能启用 FAST - 确认基表是否真有主键(
SELECT constraint_type FROM user_constraints WHERE table_name = 'T' AND constraint_type = 'P') - 运行
DBMS_MVIEW.EXPLAIN_MVIEW('MV_NAME')查看具体不支持原因,输出中capable字段为FALSE且msgtxt提到JSON即证实此限制 - 不要尝试用
FORCE刷新方式掩盖问题——它只是 fallback 到COMPLETE,不解决根本
真正难处理的是:JSON 结构动态、字段不确定时,解构到关系表的成本会上升。这时候得权衡——要么接受定期全量刷新的延迟,要么引入应用层缓存(如 Micronaut + Caffeine),而不是硬套物化视图。










