EXCHANGE PARTITION后索引失效会导致物化视图刷新失败或全表扫描;全局索引整体失效需REBUILD,本地索引个别分区失效可REBUILD PARTITION,INCLUDING INDEXES仅保定义匹配不保状态可用,修复后须同步更新统计信息。

EXCHANGE PARTITION 后索引失效,会直接导致依赖该表的物化视图(MV)刷新失败或走全表扫描——这不是 MV 定义问题,而是底层索引状态为 UNUSABLE 后,优化器无法使用索引生成高效执行计划,甚至在 REFRESH 时触发 ORA-01502。
EXCHANGE 后哪些索引会失效?怎么快速确认
只有全局索引(GLOBAL)和未显式包含的本地索引分区会变 UNUSABLE;本地索引(LOCAL)若带 INCLUDING INDEXES 子句则不受影响。但 MV 刷新常依赖全局索引加速 JOIN 或谓词过滤,一旦失效,REFRESH 就退化成暴力扫描。
立即查状态:
SELECT index_name, index_type, status FROM user_indexes WHERE table_name = 'YOUR_TABLE';
再查本地索引分区级状态(如果上面显示 status = 'VALID' 但 MV 仍慢):
SELECT index_name, partition_name, status FROM user_ind_partitions WHERE index_name IN (SELECT index_name FROM user_indexes WHERE table_name = 'YOUR_TABLE');
- 若
user_indexes.status = 'UNUSABLE'→ 全局索引整体失效,必须ALTER INDEX ... REBUILD - 若
user_ind_partitions.status = 'UNUSABLE'且user_indexes.status = 'VALID'→ 是本地索引个别分区失效,可ALTER INDEX ... REBUILD PARTITION - 若两者都
VALID但 MV 仍异常 → 很可能索引块物理损坏,需按ORA-01578路径排查
EXCHANGE 时加 INCLUDING INDEXES 不等于万无一失
INCLUDING INDEXES 只保证「交换表」上的索引定义与分区表本地索引完全匹配(列顺序、类型、长度),不保证索引内容可用。常见踩坑点:
- 临时表(
TMP_TABLE)上建了索引,但没收集统计信息 → 交换后 Oracle 认为索引“不可信”,MV 刷新跳过索引路径 - 临时表索引是
UNUSABLE状态(比如之前被ALTER INDEX ... UNUSABLE过)→INCLUDING INDEXES会原样继承该状态 - 交换前临时表有 DML 未提交,或索引处于
INPROGRESS状态 → 交换后残留中间态,status显示VALID但实际不可用
安全做法:交换前先清理临时表索引状态:
ALTER INDEX tmp_idx_name REBUILD;
再确认:
SELECT status FROM user_indexes WHERE index_name = 'TMP_IDX_NAME'; -- 必须返回 USABLE
MV 刷新卡住或报 ORA-01502?别重跑刷新,先修索引
MV 刷新失败日志里出现 ORA-01502,99% 是因为某个全局索引或其分区处于 UNUSABLE,而 MV 的刷新语句(尤其是 FAST 模式)强制依赖这些索引维护物化视图日志(MLOG$)关系。
- 不要尝试
DBMS_MVIEW.REFRESH重试——索引不修复,每次都会失败 - 不要删 MV 重建——丢失增量刷新上下文,下次
FAST刷新会退化为COMPLETE - 先定位哪个索引被 MV 引用:查
USER_MVIEWS的CONTAINERS_CHANGED和LAST_REFRESH_DATE,再结合DBA_MVIEW_LOGS关联的基表索引 - 重建索引时务必加
ONLINE(避免阻塞 MV 所在会话)和PARALLEL(加速大索引):
ALTER INDEX mv_depended_global_idx REBUILD ONLINE PARALLEL 4;
重建后立刻收集统计信息(MV 优化器严重依赖它):
EXEC DBMS_STATS.GATHER_INDEX_STATS(ownname => 'YOUR_SCHEMA', indname => 'MV_DEPENDED_GLOBAL_IDX');
为什么 MV 刷新后执行计划还是全表扫描
即使索引已 REBUILD 且状态为 VALID,MV 查询仍走全表扫描,大概率是以下两个隐形问题:
-
DBA_INDEXES.LEAF_BLOCKS或NUM_ROWS为 0 —— 统计信息没更新,优化器误判索引“空”或“低效”,直接弃用 - 索引字段存在大量
NULL值,且未建函数索引(如CREATE INDEX idx ON t(NVL(col, 'X'))),而 MV 查询条件又常含IS NOT NULL或等值判断
检查索引统计是否可信:
SELECT index_name, leaf_blocks, num_rows, clustering_factor FROM user_indexes WHERE index_name = 'YOUR_IDX';
若 num_rows = 0 或远小于表行数,必须强制收集:
EXEC DBMS_STATS.GATHER_INDEX_STATS(ownname => 'YOUR_SCHEMA', indname => 'YOUR_IDX', estimate_percent => 100);
注意:MV 自身的统计信息也要同步更新,否则查询 MV 的 SQL 仍不会用索引:
EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname => 'YOUR_SCHEMA', tabname => 'YOUR_MV_NAME');


















