pct不是建完就自动生效的,必须查运行时能力表才能确认:执行dbms_mview.explain_mview后查询mv_capabilities_table,确认'pct'和'refresh_fast_pct'两项possible均为'y'且msgtxt无否定提示,同时基表需为range/list单列分区、启用row movement,并在mv定义中显式裸露分区键。

PCT不是建完就自动生效的,必须查运行时能力表才能确认
执行 DBMS_MVIEW.EXPLAIN_MVIEW 后查 mv_capabilities_table
建完物化视图后,仅看语句里有没有 PCT 和 ENABLE QUERY REWRITE 没用。Oracle 是动态检查的,哪怕当时满足条件,后续 DDL(比如删分区、改分区键类型)也可能让 PCT 失效。
必须执行:
BEGIN DBMS_MVIEW.EXPLAIN_MVIEW('MV_NAME'); END; /
然后查:
SELECT capability_name, possible, msgtxt
FROM mv_capabilities_table
WHERE mvname = 'MV_NAME'
AND capability_name IN ('PCT', 'REFRESH_FAST_PCT')
ORDER BY seq;
-
capability_name = 'PCT'且possible = 'Y'—— 表示基础支持已识别 -
capability_name = 'REFRESH_FAST_PCT'且possible = 'Y'—— 才说明 PCT 刷新路径真正可用 - 任一
msgtxt字段含"PCT not supported"、"partition change tracking not supported"或"PCT_TABLE N",都代表失败
msgtxt 里出现 "PCT_TABLE N T关系不是一个已分区的表" 怎么办
这不是语法错误,而是 Oracle 运行时没把基表识别为有效分区表。常见原因有:
- 基表虽分区,但
USER_TAB_PARTITIONS中不可见 —— 检查是否跨 schema 引用,PCT 不支持同义词或schema.table显式写法(必须用当前用户下可解析的裸表名) - 基表用了
HASH或COMPOSITE分区 —— PCT 只认RANGE或LIST单列分区 - 分区键列在 MV 定义中被函数包装(如
TRUNC(sale_date))或重命名(如sale_date AS dt)—— 必须原样出现在SELECT和GROUP BY中
即使 REFRESH_FAST_PCT = Y,也不代表每次刷新都走 PCT 路径
PCT 刷新只响应特定 DDL,和普通 DML 无关:
- ✅ 触发 PCT:执行了
ALTER TABLE ... SPLIT PARTITION、EXCHANGE PARTITION、TRUNCATE PARTITION、DROP PARTITION - ❌ 不触发 PCT:任何
INSERT/UPDATE/DELETE,哪怕只改一个分区的数据 —— 这类变更仍依赖物化视图日志,走普通FAST路径 - ⚠️ 注意:如果手动调用
DBMS_MVIEW.REFRESH且未指定method => 'FORCE'或'FAST',Oracle 默认可能 fallback 到COMPLETE,完全绕过 PCT
最常被忽略的一点:PCT 生效的前提是基表启用了 ROW MOVEMENT。漏掉 ALTER TABLE t ENABLE ROW MOVEMENT,哪怕所有能力检查都通过,SPLIT 或 EXCHANGE 时也会因日志不一致而静默降级为全量刷新。











