必须显式添加 count(*),且物化视图日志需覆盖所有 group by 和聚合列,并指定 with rowid、sequence(列列表)、including new values;否则 refresh fast 直接报错或降级为完全刷新。
必须显式加 count(*),且物化视图日志要覆盖所有参与聚合和 group by 的列,否则 refresh fast 直接报错——不是慢,是根本拒绝执行。
为什么加了 SUM() 还必须写 COUNT(*)
Oracle 不靠 SUM() 判断行级变更是否影响结果:一条记录插入后 SUM(salary) 可能因值为 0 或正负抵消而不变,但行数一定变。COUNT(*) 是唯一能稳定反映“增/删/改了多少行”的信号。没有它,快速刷新逻辑无法建立增量映射关系,直接抛 ORA-12052。
-
COUNT(1)、COUNT(salary)、COUNT(DISTINCT job)全都不行,只认COUNT(*) - 不能用别名覆盖,例如
COUNT(*) cnt可以,但1 AS COUNT(*)会解析失败 - 如果基表某列允许
NULL,又用了COUNT(col),则快速刷新被禁用(COUNT(*)不受此限)
CREATE MATERIALIZED VIEW LOG 必须带哪些参数
日志不是“建了就行”,字段缺失或参数错配会导致 ORA-32320 或静默降级为完全刷新。
- 必须含
WITH ROWID, SEQUENCE (col1, col2):括号里填所有GROUP BY列 + 所有被聚合函数直接读取的列(如SUM(salary)→salary必须在括号中) - 必须加
INCLUDING NEW VALUES:否则UPDATE场景下无法捕获旧值→新值变化,SUM/COUNT增量修正失效 - 不推荐仅用
WITH PRIMARY KEY:它默认只记主键和ROWID,不自动包含非主键的聚合输入列(如salary),极易触发ORA-32320 - 查日志是否生效:
SELECT COLUMN_NAME FROM USER_MVIEW_LOG_FILTER_COLS WHERE LOG_TABLE = 'MLOG$_EMP',结果里必须出现你用到的所有列
REFRESH FAST 失败时怎么快速定位缺哪块
别急着重建 MV,先确认三处是否对齐:物化视图定义、日志结构、基表约束。
- 运行
SELECT TEXT FROM DBA_VIEWS WHERE VIEW_NAME = 'MV_SALES_SUM',看 SELECT 列里有没有未出现在日志SEQUENCE列表中的字段(比如多写了emp_name但日志没记它) - 查
USER_MVIEW_LOGS中对应日志的SEQUENCE和INCLUDES_NEW_VALUES字段,二者都必须是YES - 基表若无主键或唯一约束,
REFRESH FAST会被 Oracle 主动拒绝(即使日志和 MV 都写对了) - 避免用
AVG(salary):它不支持快速刷新,必须拆成SUM(salary) sum_sal, COUNT(*) cnt,后续业务层算sum_sal / cnt
最容易被忽略的是日志的 INCLUDING NEW VALUES —— 它不是可选项,而是 SUM/COUNT 类聚合快速刷新的硬门槛;漏掉它,哪怕 COUNT(*) 和日志列全对,刷新也会退化为 COMPLETE,且不报错、只悄悄变慢。











